package fj.data;

import static fj.data.Validation.parseInt;
import static fj.data.Validation.condition;
import fj.P3;
import fj.P;
import fj.Bottom;
import fj.pre.Semigroup;
import fj.pre.Show;
import static fj.pre.Show.validationShow;
import static fj.pre.Show.nonEmptyListShow;
import static fj.pre.Show.stringShow;
import static fj.pre.Show.p3Show;
import static fj.pre.Show.intShow;
import static fj.pre.Show.booleanShow;

import static java.lang.Character.isUpperCase;

public final class ValidationTest {
static final Show<Validation<NonEmptyList<String>, P3<Integer, String, Boolean>>> show =
validationShow(nonEmptyListShow(stringShow), p3Show(intShow, stringShow, booleanShow));

public static void main(final String[] args) {
// age must parse as an integer, otherwise, return the exception's toString
final Validation<String, Integer> age = parseInt(args[0]).f().map(Bottom.<NumberFormatException>eToString());

// name must start with a capital letter
final Validation<String, String> name = condition(!args[1].isEmpty() && isUpperCase(args[1].charAt(0)),
"First character of the name must be upper-case", args[1]);

// must be "male" or "female" or error message
final Validation<String, Boolean> female = args[2].equals("female") ?
Validation.<String, Boolean>success(true) :
args[2].equals("male") ?
Validation.<String, Boolean>success(false) :
Validation.<String, Boolean>fail("gender must be male or female");

// accumulate validation
final Validation<NonEmptyList<String>, P3<Integer, String, Boolean>> acc =
age.nel().accumulate(Semigroup.<String>nonEmptyListSemigroup(), name.nel(), female.nel(), P.<Integer, String, Boolean>p3());

// well?
show.println(acc);
}
}

/*
> java ValidationTest 42 Bob male
Success((42,Bob,false))

> java ValidationTest 27 Mary female
Success((27,Mary,true))

> java ValidationTest x Bob male
Fail([java.lang.NumberFormatException: For input string: "x"])

> java ValidationTest 23 mary female
Fail([First character of the name must be upper-case])

> java ValidationTest 46 Bob both
Fail([gender must be male or female])

> java ValidationTest old mary female
Fail([java.lang.NumberFormatException: For input string: "old",First character of the name must be upper-case])

> java ValidationTest old Bob neither
Fail([java.lang.NumberFormatException: For input string: "old",gender must be male or female])

> java ValidationTest 42 mary neither
Fail([First character of the name must be upper-case,gender must be male or female])

> java ValidationTest young fred none
Fail([java.lang.NumberFormatException: For input string: "young",First character of the name must be upper-case,gender must be male or female])
*/