package org.biomoby.shared.data.test;

import org.biomoby.shared.data.MobyDataDateTime;

import junit.framework.*;
import java.util.*;

public class MobyDataDateTimeTestCase extends TestCase{

    public MobyDataDateTimeTestCase(String testName){
	super(testName);
    }

    public void testIdentity(){
	String dateAsString = "2007-04-20T18:43:39-04:00";
	MobyDataDateTime timeObject = new MobyDataDateTime(dateAsString);

	Calendar localTime = Calendar.getInstance();
	localTime.set(2007, // year
		      3,    // month, zero-based
		      20,   // day-of-the-month
		      14,   // hour-of-the-day (18-4)
		      43,   // minute
		      39    // second
		      );	
	localTime.set(Calendar.MILLISECOND, 0);
	localTime.setTimeZone(TimeZone.getTimeZone("GMT-4:00"));

	long timeDiff = localTime.getTimeInMillis() - ((Calendar) timeObject.getObject()).getTimeInMillis();
	assertTrue("The date parsing is incorrect, MobyDataDateTime.getObject() does " +
		   "not equal the input calendar object (Time difference is " + timeDiff + "ms)",
		   timeDiff == 0);

	assertTrue("The date printing is incorrect, expected "+dateAsString+
		   ", but got " + timeObject.toString(), 
		   timeObject.toString().equals(dateAsString));
	
    }

    public void testCentralEuropeTimes(){
	TimeZone timeZoneParis = TimeZone.getTimeZone("Europe/Paris");
	assertNotNull("Could not find the Europe/Paris time zone from the system", timeZoneParis);

	Calendar localTimeParis = Calendar.getInstance(timeZoneParis);
	assertTrue("Time returned by the system was not a GregorianCalendar as expected", 
		   localTimeParis instanceof GregorianCalendar);

	// The following should be daylight savings time i.e. Z+2
	localTimeParis.set(2007, // year
			   4,    // month, zero-based
                           21,   // day-of-the-month
			   2,    // hour-of-the-day
			   40,   // minute
                           35    // second
			   );
	String dateAsString = "2007-05-21T00:40:35+02:00";

	MobyDataDateTime timeObject = new MobyDataDateTime((GregorianCalendar) localTimeParis);
	assertTrue("The date parsing/printing is incorrect, expected "+dateAsString+
		   ", but got " + timeObject.toString(), 
		   timeObject.toString().equals(dateAsString));

	// The following should NOT be daylight savings time (January), hence Z+1
	localTimeParis.set(Calendar.MONTH, 0);
	dateAsString = "2007-01-21T01:40:35+01:00";
	
	timeObject = new MobyDataDateTime((GregorianCalendar) localTimeParis);
	assertTrue("The date parsing/printing is incorrect, expected "+dateAsString+
		   ", but got " + timeObject.toString(), 
		   timeObject.toString().equals(dateAsString));
	
	// Try a time that spans a month boundary from GMT to local
	dateAsString = "2007-01-31T23:40:35+01:00";
	localTimeParis.set(2007, // year
			   1,    // month, zero-based
                           1,    // day-of-the-month
			   0,    // hour-of-the-day
			   40,   // minute
                           35    // second
			   );

	timeObject = new MobyDataDateTime((GregorianCalendar) localTimeParis);
	assertTrue("The date parsing/printing is incorrect (over month boundary), expected "+dateAsString+
		   ", but got " + timeObject.toString(), 
		   timeObject.toString().equals(dateAsString));
    }

    /**
     * Interesting because offset is GMT-3.5 (a half-hour time zone).  Also tests morning/afternoon boundary
     */
    public void testNewfoundlandTime(){
	TimeZone timeZoneStJ = TimeZone.getTimeZone("America/St_Johns");

	assertNotNull("Could not find the America/St_Johns time zone from the system", timeZoneStJ);
	Calendar localTimeStJ = Calendar.getInstance(timeZoneStJ);
	assertTrue("Time returned by the system was not a GregorianCalendar as expected", 
		   localTimeStJ instanceof GregorianCalendar);

	// The following should be daylight savings time i.e. Z+2.5
	localTimeStJ.set(2007, // year
			 4,    // month, zero-based
			 21,   // day-of-the-month
			 10,   // hour-of-the-day
			 40,   // minute
			 35    // second
			 );
	String dateAsString = "2007-05-21T13:10:35-02:30";

	MobyDataDateTime timeObject = new MobyDataDateTime((GregorianCalendar) localTimeStJ);
	assertTrue("The date parsing/printing is incorrect, expected "+dateAsString+
		   ", but got " + timeObject.toString(), 
		   timeObject.toString().equals(dateAsString));
	
    }

    /**
     * @return a test suite for all the test methods of this test case.
     */
    public static Test suite() {
        TestSuite suite = new TestSuite(); 
        suite.addTest(new MobyDataDateTimeTestCase("testIdentity")); //done
	suite.addTest(new MobyDataDateTimeTestCase("testCentralEuropeTimes")); //done
	suite.addTest(new MobyDataDateTimeTestCase("testNewfoundlandTime"));
        return suite;
    }

    /**
     * Runs the test suite when the class is invoked on the command line.
     */
    public static void main(String[] args) throws Exception{
        junit.textui.TestRunner.run(suite());
    }

}
