package hirondelle.web4j.model;

import hirondelle.web4j.security.SafeText;
import java.util.*;
import java.math.*;
import java.util.regex.*;
import junit.framework.*;
import java.io.FileNotFoundException;

public final class TESTCheck extends TestCase {

  /** Run the test cases. */
  public static void main(String args[]) throws AppException, FileNotFoundException {
    String[] testCaseName = { TESTCheck.class.getName() };
    junit.textui.TestRunner.main(testCaseName);
  }

  public TESTCheck( String aName) {
    super(aName);
  }

  // TEST CASES //
  
  public void testRequired(){
    Object thing = null;
    assertFalse(Check.required(thing));
    thing = new Object();
    assertTrue(Check.required(thing));
  }
  
  public void testIntegerRange(){
    Validator[] validators = {Check.min(1), Check.max(10)};
    assertTrue(Check.required(new Integer(1), validators));
    assertTrue(Check.required(new Integer(2), validators));
    assertTrue(Check.required(new Integer(10), validators));
    
    assertFalse(Check.required(new Integer(0), validators));
    assertFalse(Check.required(new Integer(-1), validators));
    assertFalse(Check.required(new Integer(-50), validators));
    assertFalse(Check.required(new Integer(11), validators));
    assertFalse(Check.required(new Integer(50), validators));
  }
  
  public void testLongRange(){
    Validator[] validators = {Check.min(1L), Check.max(10L)};
    assertTrue(Check.required(new Long(1L), validators));
    assertTrue(Check.required(new Long(2L), validators));
    assertTrue(Check.required(new Long(10L), validators));
    assertFalse(Check.required(new Long(0L), validators));
    assertFalse(Check.required(new Long(-1L), validators));
    assertFalse(Check.required(new Long(-50L), validators));
    assertFalse(Check.required(new Long(11L), validators));
    assertFalse(Check.required(new Long(50L), validators));
  }
  
  public void testString(){
    Validator[] validators = {Check.min(1), Check.max(10)};
    assertTrue(Check.required("1", validators));
    assertTrue(Check.required("123", validators));
    assertTrue(Check.required("123456789", validators));
    assertTrue(Check.required("1234567890", validators));
    assertTrue(Check.required("This is th", validators));
    assertTrue(Check.required("This is", validators));
    
    assertFalse(Check.required(null, validators));
    assertFalse(Check.required("", validators));
    assertFalse(Check.required(" ", validators));
    assertFalse(Check.required("  ", validators));
  }
  
  public void testId(){
    Validator[] validators = {Check.min(1), Check.max(10)};
    assertTrue(Check.required(new Id("1"), validators));
    assertTrue(Check.required(new Id("123"), validators));
    assertTrue(Check.required(new Id("123456789"), validators));
    assertTrue(Check.required(new Id("1234567890"), validators));
    assertTrue(Check.required(new Id("Yes What"), validators));
    
    assertFalse(Check.required(null, validators));
    assertFalse(Check.required(new Id("12345678901"), validators));
    assertFalse(Check.required(new Id(""), validators));
  }

  public void testFreeFormText(){
    Validator[] validators = {Check.min(1), Check.max(10)};
    assertTrue(Check.required(new SafeText("1"), validators));
    assertTrue(Check.required(new SafeText("123"), validators));
    assertTrue(Check.required(new SafeText("123456789"), validators));
    assertTrue(Check.required(new SafeText("1234567890"), validators));
    assertTrue(Check.required(new SafeText("Yes What"), validators));
    assertTrue(Check.required(new SafeText("Yes"), validators));
    assertTrue(Check.required(new SafeText("That's it."), validators));
    assertTrue(Check.required(new SafeText("& co."), validators));
    
    assertFalse(Check.required(null, validators));
    assertFalse(Check.required(new SafeText("12345678901"), validators));
    assertFalse(Check.required(new SafeText(""), validators));
  }
  
  
  public void testCollection() {
    Validator[] validators = {Check.min(1), Check.max(3)};
    assertTrue(Check.required(getList("1"), validators));
    assertTrue(Check.required(getList("1", "2"), validators));
    assertTrue(Check.required(getList("1", "2", "3"), validators));
    
    assertFalse(Check.required(null, validators));
    assertFalse(Check.required(Collections.EMPTY_LIST, validators));
    assertFalse(Check.required(getList("1", "2", "3", "4"), validators));
  }
  
  public void testMap() {
    Validator[] validators = {Check.min(1), Check.max(3)};
    Map<String, String> map = new HashMap<String, String>();
    map.put("A", "1");
    assertTrue(Check.required(map, validators));
    map.put("B", "2");
    assertTrue(Check.required(map, validators));
    map.put("C", "3");
    assertTrue(Check.required(map, validators));
    
    assertFalse(Check.required(null, validators));
    assertFalse(Check.required(Collections.EMPTY_MAP, validators));
    map.put("D", "4");
    assertFalse(Check.required(map, validators));
  }
  
  public void testDate() {
    Date start = new Date(62,2,1);
    Date end = new Date(62,2,3);
    Validator[] validators = {Check.min(start.getTime()), Check.max(end.getTime())};
    Date test = new Date(62,2,1);
    assertTrue(Check.required(test, validators));
    test = new Date(62,2,2);
    assertTrue(Check.required(test, validators));
    test = new Date(62,2,3);
    assertTrue(Check.required(test, validators));
    
    assertFalse(Check.required(null, validators));
    test = new Date(62,1,28);
    assertFalse(Check.required(test, validators));
    test = new Date(62,2,4);
    assertFalse(Check.required(test, validators));
  }
  
  public void testCalendar() {
    Calendar start = new GregorianCalendar();
    start.set(2006, 8, 9); 
    Calendar end = new GregorianCalendar();
    end.set(2006, 8, 11); 
    
    Validator[] validators = {Check.min(start.getTimeInMillis()), Check.max(end.getTimeInMillis())};
    Calendar test = new GregorianCalendar();
    test.set(2006,8,9);
    assertTrue(test.toString(), Check.required(test, validators));
    test.set(2006,8,10);
    assertTrue(test.toString(), Check.required(test, validators));
    test.set(2006,8,11);
    assertTrue(test.toString(), Check.required(test, validators));
    
    assertFalse("Versus null", Check.required(null, validators));
    test.set(2006,8,8);
    assertFalse(test.toString(), Check.required(test, validators));
    test.set(2006,8,12);
    assertFalse(test.toString(), Check.required(test, validators));
  }
  
  public void testOptional(){
    Validator[] validators = {Check.min(1), Check.max(10)};
    assertTrue(Check.optional(null, validators));
    assertTrue(Check.optional(new Integer(1), validators));
    assertTrue(Check.optional(new Integer(2), validators));
    assertTrue(Check.optional(new Integer(10), validators));
    
    assertFalse(Check.optional(new Integer(0), validators));
    assertFalse(Check.optional(new Integer(-1), validators));
    assertFalse(Check.optional(new Integer(-50), validators));
    assertFalse(Check.optional(new Integer(11), validators));
    assertFalse(Check.optional(new Integer(50), validators));
  }
  
  public void testBigDecimal(){
    Validator[] validators = {Check.min(new BigDecimal("1.25")), Check.max(new BigDecimal("10.75")) };
    assertTrue(Check.required(new BigDecimal("1.25"), validators));
    assertTrue(Check.required(new BigDecimal("10.75"), validators));
    assertTrue(Check.required(new BigDecimal("1.26"), validators));
    assertTrue(Check.required(new BigDecimal("10.74"), validators));
    assertTrue(Check.required(new BigDecimal("9"), validators));
    
    assertFalse(Check.required(new BigDecimal("1.24"), validators));
    assertFalse(Check.required(new BigDecimal("10.750001"), validators));
    assertFalse(Check.required(new BigDecimal("1.249999"), validators));
    assertFalse(Check.required(new BigDecimal("1"), validators));
    assertFalse(Check.required(new BigDecimal("10.76"), validators));
    assertFalse(Check.required(new BigDecimal("-1"), validators));
    assertFalse(Check.required(new BigDecimal("-1.25"), validators));
    assertFalse(Check.required(new BigDecimal("1000"), validators));
  }
  
  public void testPattern(){
    Pattern idPattern = Pattern.compile("(\\d){4}-(\\d){4}");
    Validator validator = Check.pattern(idPattern);
    assertTrue(Check.required("1234-1234", validator));
    assertTrue(Check.required("9845-9852", validator));
    assertTrue(Check.required("0000-0000", validator));
    assertTrue(Check.required("9999-9999", validator));
    
    assertFalse(Check.required(null, validator));
    assertFalse(Check.required("12345678", validator));
    assertFalse(Check.required("", validator));
    assertFalse(Check.required(" ", validator));
    assertFalse(Check.required("A", validator));
    assertFalse(Check.required("A234-9955", validator));
    assertFalse(Check.required("Blah", validator));
    assertFalse(Check.required("1234-5678 ", validator));
    assertFalse(Check.required(" 1234-5678", validator));
    assertFalse(Check.required("1 234-5678", validator));
    assertFalse(Check.required("1234- 5678", validator));
    assertFalse(Check.required("1234 - 5678", validator));
    assertFalse(Check.required("1234 -5678", validator));
  }
  
  public void testCheckEmail(){
    Validator validator = Check.email();
    assertTrue(Check.required("john@blah.com", validator));
    assertTrue(Check.required("x@y.c", validator));
    assertTrue(Check.required("john@blah", validator));
    assertTrue(Check.required("john@blah.com ", validator)); 
   assertTrue(Check.required(" john@blah.com", validator));
    
    assertFalse(Check.required("john", validator));
    assertFalse(Check.required(null, validator));
    assertFalse(Check.required(" ", validator));
    assertFalse(Check.required("", validator));
    assertFalse(Check.required("john@", validator));
    //These are actually OK :
    assertFalse(Check.required("john @blah.com", validator));
    assertFalse(Check.required("john@ blah.com", validator));
    assertFalse(Check.required("john@blah. com", validator));
    assertFalse(Check.required("john@blah .com", validator));
  }
  
  public void testLongRange2(){
    Validator validator = Check.range(1,10);
    assertTrue( validator.isValid(new Long(1)));
    assertTrue( validator.isValid(new Long(2)));
    assertTrue( validator.isValid(new Long(9)));
    assertTrue( validator.isValid(new Long(10)));
    assertTrue( Check.required(new Long(5), validator));
    
    assertFalse( validator.isValid(new Long(0)));
    assertFalse( validator.isValid(new Long(11)));
    assertFalse( Check.required(new Long(0), validator));
  }
  
  public void testRangeBigDecimal(){
    Validator validator = Check.range(new BigDecimal("0.01"), new BigDecimal("10.00"));
    assertTrue( Check.required( new BigDecimal("0.01"), validator));
    assertTrue( Check.required( new BigDecimal("0.02"), validator));
    assertTrue( Check.required( new BigDecimal("1.00"), validator));
    assertTrue( Check.required( new BigDecimal("5.00"), validator));
    assertTrue( Check.required( new BigDecimal("9.99"), validator));
    assertTrue( Check.required( new BigDecimal("10.00"), validator));
    
    assertFalse( Check.required( new BigDecimal("0.00"), validator));
    assertFalse( Check.required( new BigDecimal("10.01"), validator));
    assertFalse( Check.required( new BigDecimal("1000.00"), validator));
    assertFalse( Check.required( new BigDecimal("-0.00"), validator));
    assertFalse( Check.required( new BigDecimal("-0.01"), validator));
  }
  
  
  // FIXTURE //
  
  protected void setUp(){
  }

  protected void tearDown() {
  }

  // PRIVATE  //
  
  private List<String> getList(String... aStrings){
    return Arrays.asList(aStrings);
  }
}
