package hirondelle.web4j.model;

import java.util.*;
import java.io.FileNotFoundException;
import java.math.*;
import java.util.regex.*;
import junit.framework.*;
import static hirondelle.web4j.model.ModelUtil.NullsGo;

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

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

  // TEST CASES //
  
   public void testStrings(){
     assertTrue(compareStringsNullsLast("aaa", "bbb", BEFORE));
     assertTrue(compareStringsNullsLast("ccc", "bbb", AFTER));
     assertTrue(compareStringsNullsLast("ccc", null , BEFORE));
     assertTrue(compareStringsNullsLast(null, "ccc" , AFTER));
     assertTrue(compareStringsNullsLast("ccc", "ccc", EQUAL));
     assertTrue(compareStringsNullsLast("ccc", "CCC", AFTER));
     
     assertTrue(compareStringsNullsFirst("aaa", "bbb", BEFORE));
     assertTrue(compareStringsNullsFirst("ccc", "bbb", AFTER));
     assertTrue(compareStringsNullsFirst("ccc", null , AFTER));
     assertTrue(compareStringsNullsFirst(null, "ccc" , BEFORE));
     assertTrue(compareStringsNullsFirst("ccc", "ccc", EQUAL));
     assertTrue(compareStringsNullsFirst("ccc", "CCC", AFTER));
   }
   
   public void testTypicalObject(){
     Person bob = new Person();
     assertTrue(compareObjectsNullsLast(bob, bob, EQUAL));
     
     Person peter = new Person();
     peter.setName("Peter");
     assertTrue(compareObjectsNullsLast(bob, peter, BEFORE));
     
     Person andrea = new Person();
     andrea.setName("Andrea");
     assertTrue(compareObjectsNullsLast(bob, andrea, AFTER));
     assertTrue(compareObjectsNullsLast(andrea, bob, BEFORE));

     assertTrue(compareObjectsNullsLast(bob, null, BEFORE));
     assertTrue(compareObjectsNullsLast(null, bob, AFTER));
     
     Person noName = new Person();
     noName.setName(null);
     assertTrue(compareObjectsNullsLast(bob, noName, BEFORE));
     assertTrue(compareObjectsNullsLast(noName, bob, AFTER));
     
     Person bobTwo = new Person();
     bobTwo.setName("Bob");
     assertTrue(compareObjectsNullsLast(bob, bobTwo, EQUAL));
     assertTrue(compareObjectsNullsLast(bobTwo, bob, EQUAL));
     
     Person bobOld = new Person();
     bobOld.setBirthDate(new Date(22,2,1));
     assertTrue(compareObjectsNullsLast(bob, bobOld, AFTER));
     assertTrue(compareObjectsNullsLast(bobOld, bob, BEFORE));

     Person bobSame = new Person();
     bobSame.setBirthDate(new Date(45,3,3));
     assertTrue(compareObjectsNullsLast(bob, bobSame, EQUAL));
     assertTrue(compareObjectsNullsLast(bobSame, bob, EQUAL));
     
     Person bobYoung = new Person();
     bobYoung.setBirthDate(new Date(63,2,1));
     assertTrue(compareObjectsNullsLast(bob, bobYoung, BEFORE));

     Person bobYoung2 = new Person();
     bobYoung2.setAge(10);
     assertTrue(compareObjectsNullsLast(bob, bobYoung2, AFTER));
     
     Person bobOld2 = new Person();
     bobOld2.setAge(100);
     assertTrue(compareObjectsNullsLast(bob, bobOld2, BEFORE));
     
     Person poor = new Person();
     poor.setSalary(new BigDecimal("10"));
     assertTrue(compareObjectsNullsLast(bob, poor, AFTER));
     
     Person rich = new Person();
     rich.setSalary(new BigDecimal("1000"));
     assertTrue(compareObjectsNullsLast(bob, rich, BEFORE));
   }
   
   //test how a collection will sort items? worth it...
   public void testCollection(){
     Set<Person> items = new TreeSet<Person>(); //sorts the items 
     
     Person bob = new Person();
     
     Person andrea = new Person();
     andrea.setName("Andrea");
     
     Person noName = new Person();
     noName.setName("");
     
     Person nobody = new Person();
     nobody.setName(null);
     
     items.add(bob);
     items.add(andrea);
     items.add(noName);
     items.add(nobody);
     
     //Informal : just print it out
     //System.out.println(items);
   }
   
   // PRIVATE //
   private static final int BEFORE = -1;
   private static final int AFTER = 1;
   private static final int EQUAL = 0;
   
   private boolean compareStringsNullsLast(String aThis, String aThat, int aExpectedResult) {
     int result = ModelUtil.comparePossiblyNull(aThis, aThat, NullsGo.LAST);
     return sign(result) == aExpectedResult;
   }
   
   private boolean compareStringsNullsFirst(String aThis, String aThat, int aExpectedResult) {
     int result = ModelUtil.comparePossiblyNull(aThis, aThat, NullsGo.FIRST);
     return sign(result) == aExpectedResult;
   }
   
   private boolean compareObjectsNullsLast(Comparable aThis, Comparable aThat, int aExpectedResult) {
     int result = ModelUtil.comparePossiblyNull(aThis, aThat, NullsGo.LAST);
     return sign(result) == aExpectedResult;
   }
   
   private int sign(int aNumber){
     int result = 0;
     if (aNumber > 0){ 
       result = 1;
     }
     else if (aNumber < 0){
       result = -1;
     }
     return result;
   }
   
   private static final class Person implements Comparable<Person> {
      Person(String aName, Integer aAge, Date aBirthDate, BigDecimal aSalary){
        fName = aName;
        fAge = aAge;
        fBirthDate = aBirthDate;
        fSalary = aSalary;
      }
      Person(){
        fName = "Bob";
        fAge = new Integer(65);
        fBirthDate = new Date(45,3,3);
        fSalary = new BigDecimal("123.45");
      }
      void setName(String aName){ fName = aName; }
      void setAge(Integer aAge){ fAge = aAge; }
      void setBirthDate(Date aBirthDate){ fBirthDate = aBirthDate; }
      void setSalary(BigDecimal aSalary){ fSalary = aSalary; }
      public String toString() { return fName; }
      public int compareTo(Person aThat) {
        if ( this == aThat ) return EQUAL;
        
        int comparison = ModelUtil.comparePossiblyNull(this.fName, aThat.fName, NullsGo.LAST);
        if ( comparison != EQUAL ) return comparison;

        comparison = ModelUtil.comparePossiblyNull(this.fAge, aThat.fAge, NullsGo.LAST);
        if ( comparison != EQUAL ) return comparison;
       
        comparison = ModelUtil.comparePossiblyNull(this.fBirthDate,  aThat.fBirthDate, NullsGo.LAST);
        if ( comparison != EQUAL ) return comparison;
        
        comparison = ModelUtil.comparePossiblyNull(this.fSalary,  aThat.fSalary, NullsGo.LAST);
        if ( comparison != EQUAL ) return comparison;
        
        return EQUAL;
      }
      //assume all these can be null
      private String fName;
      private Integer fAge;
      private Date fBirthDate;
      private BigDecimal fSalary;
   }
}
