package com.fujitsu.iflowqa.testframe;


import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.SimpleTimeZone;

import com.fujitsu.iflow.server.impl.timerfactoryimpl.BusinessCalendar;

/**
* This class implements TestSet and the purpose of this class to test
* BusinessCalendar For Timers. The results of the test are recorded using
* TestRecorder class.
*/
public class TestBusinessCalendar extends BPMTestBase implements TestSet
{

    //get the calendar given the timeZone=GMT-8:00
    private
    Calendar
    getCalendar(
        int mStart,int mEnd, int dd, int dst)
    {
        SimpleTimeZone tZone = new SimpleTimeZone(-8*60*60*1000,"");
        Calendar cal = new GregorianCalendar(tZone);
        cal.set(Calendar.YEAR, 2004);
        cal.set(Calendar.MONTH, Calendar.FEBRUARY);
        cal.set(Calendar.DAY_OF_MONTH, 1);
        cal.set(Calendar.HOUR_OF_DAY, 8);
        cal.set(Calendar.MINUTE, 30);
        cal.set(Calendar.SECOND,0);

        return cal;
    }

    public
    void
    runTests(
        TestRecorder tr)
        throws Exception
    {
        //initialize the BPMTestBase super class
        init(tr);

        Calendar currCal = getCalendar(4, 10, 21, 1);
        long expectedAnswer;
        String expr;

        long startTime = currCal.getTime().getTime();
        try{

            expr = "Expr1: Timer should expire after 6 business hours. {BT(6:0:0);}";
            computeTimerExpression(startTime,"BT(6:0:0);", 1075761000, expr);

            expr = "Expr2: Timer should expire on november 1st at 10:00 am. {DY(1);RM(10);AT(10:00:00);}";
            computeTimerExpression(startTime,"DY(1);RM(10);AT(10:00:00);", 1099332000, expr);

            expr = "Expr3: Timer should expire after 2 business days from Feb 1. {BD(2);}: ";
            computeTimerExpression(startTime,"BD(2);", 1075912200, expr);

            expr = "Expr4: Timer should expire after 2 business days and the at absoluteTime. {BD(2);AT(10);}";
            computeTimerExpression(startTime,"BD(2);AT(10);", 1075917600, expr);

            expr = "Expr5: Timer should expire after 2 business days and 2 hours before the end of the day. {BD(2);CT(-2);}";
            computeTimerExpression(startTime,"BD(2);CT(-2);", 1075939200, expr);

            expr = "Expr6: Timer should expire after 2 weeks from now and at 10:00 am(absolute time). {RD(14);AT(10);}";
            computeTimerExpression(startTime,"RD(14);AT(10);", 1076868000, expr);

            expr = "Expr7: Timer should expire after 2 weeks and 3 hours after the start Time. {RD(14);OT(3);}";
            computeTimerExpression(startTime,"RD(14);OT(3);", 1076959800, expr);

            expr = "Expr:8 Timer should expire after one week and on Thrusday of the week at 10:00 am. {RD(7);WD(5);AT(10);}";
            computeTimerExpression(startTime,"RD(7);WD(5);AT(10);", 1076608800, expr);

            expr = "Expr:9 Timer should expire after one week and on Thrusday of the week and 3 hours before the close time. {RD(7);WD(5);CT(-3);}";
            computeTimerExpression(startTime,"RD(7);WD(5);CT(-3);", 1076626800, expr);


            expr = "Expr:10 Timer should expire after 2 months and the 12:00 am of that day. {RM(2);BT(0);AT(12);}";
            computeTimerExpression(startTime,"RM(2);BT(0);AT(12);", 1080849600, expr);

            expr = "Expr:11 Timer should expire after 2 months and 3 hours before the end of the day. {RM(5);CT(-3);}";
            computeTimerExpression(startTime,"RM(2);BT(0);CT(-3);", 1080860400, expr);


            expr = "Expr:12 Timer should expire after 2 months {RM(2);}";
            computeTimerExpression(startTime,"RM(2)",1080837000, expr);

            expr = "Expr:13 Timer should expire after 2 months, 1st business day of that month. {RM(2);BM(1)}";
            computeTimerExpression(startTime,"RM(2);BM(1)",1080837000, expr);

            expr = "Expr:14 Timer should expire after 2 months, 2nd business day of that month. {RM(2);BM(2)}";
            computeTimerExpression(startTime,"RM(2);BM(2)",1080923400, expr);

            expr = "Expr:15 Timer should expire after 2 months, 3rd business day of that month. {RM(2);BM(3)}";
            computeTimerExpression(startTime,"RM(2);BM(3)",1081179000, expr);

            expr = "Expr:16 Timer should expire after 2 months and 4th business day of that month at 8:00 am. {RM(2);BM(4);AT(8);}";
            computeTimerExpression(startTime,"RM(2);BM(4);AT(8);", 1081263600, expr);

            expr = "Expr:17 Timer should expire after 2 months and 4th business day of that month an 2 hours before the end of the day. {RM(2);BM(-1);CT(-2);}: " ;
            computeTimerExpression(startTime,"RM(2);BM(4);CT(-2);", 1081292400, expr);

            expr = "Expr:18 Timer should expire after 2months and fourth friday of that month and at 10:00 am of that day. {RM(2);DM(1);RD(-1);WN(6);RD(21);AT(10);}: ";
            computeTimerExpression(startTime,"RM(2);DM(1);RD(-1);WN(6);RD(21);AT(10);", 1082739600, expr);

            expr = "Expr:19 Timer should expire after 2months and fourth friday of that month and at 3 hrs before the close time. {RM(2);DM(1);RD(-1);WN(6);RD(21);CT(-3);}: ";
            computeTimerExpression(startTime,"RM(2);DM(1);RD(-1);WN(6);RD(21);CT(-3);", 1082757600, expr);


            expr = "Expr20: Timer should use different calendar 'FSW_USA', and timer should expire after 2 days and at 10:00 am. {UC(FSW_USA);RD(2);AT(10);}: ";
            computeTimerExpression(startTime,"UC(FSW_USA);RD(2);AT(10);", 1075831200, expr);

            expr = "Expr21: Timer should use different calendar 'FSW_USA', and timer should expire after 2 business hours later. {UC(FSW_USA);BT(2)}";
            computeTimerExpression(startTime,"UC(FSW_USA);BT(2)",1075746600, expr);


            expr = "Expr22: Timer should expire after 2 relative days and at the business time. {RD(2);BT(-0);}: ";
            computeTimerExpression(startTime,"RD(2);BT(-0);",  1075825800, expr);


        }catch(Exception ex){
            throw new ExceptionWrapper("Exception in TestBusinessCalendar runTests", ex);
        }
    }

    private
    void
    computeTimerExpression(
        long startTime,
        String expression,
        long expectedTime,
        String outMsg)
        throws Exception
    {
        long realTimeInMillis = -1;
        realTimeInMillis = BusinessCalendar.computeTimerTime(startTime, expression, "TestBusinessCal",tr.getTestDir());

        long resultTime = realTimeInMillis/1000;
        int diffTime = Math.abs((int)(resultTime-expectedTime));

        if (diffTime <= 1000) {
            tr.markPassed(outMsg);
        }
        else {
            StringBuffer sb = new StringBuffer();
            sb.append("\nStart date: ");
            sb.append(new Date(startTime).toString());
            sb.append("\nExpression: ");
            sb.append(expression);
            sb.append("\nExpected: ");
            sb.append(new Date(expectedTime * 1000).toString());
            sb.append("\nGot: " + resultTime);
            sb.append(new Date(realTimeInMillis).toString());
            tr.markFailed(outMsg, sb.toString());
        }

    }

    /**
    * TestDriver is the class that knows how to run these tests.
    * So just call it with the name of this class in there.
    */
    public
    static
    void
    main(String[] args) {
        String[] newArgs = new String[1];
        newArgs[0] = "com.fujitsu.iflowqa.testframe.TestBusinessCalendar";
        TestDriver.main(newArgs);
    }

}
