package com.fujitsu.iflowqa.testframe;

import java.awt.Point;

import com.fujitsu.iflow.model.workflow.DataItemRef;
import com.fujitsu.iflow.model.workflow.JavaAction;
import com.fujitsu.iflow.model.workflow.JavaActionSet;
import com.fujitsu.iflow.model.workflow.Node;
import com.fujitsu.iflow.model.workflow.Plan;
import com.fujitsu.iflow.model.workflow.ProcessInstance;
import com.fujitsu.iflow.model.workflow.TimerAction;
import com.fujitsu.iflow.model.workflow.TimerDef;
import com.fujitsu.iflow.model.workflow.WFObjectFactory;
import com.fujitsu.iflow.model.workflow.WFSession;

/**
* This class implements TestSet and the purpose of this class to test
* Timer. To run this class iFlowClients.properties file should be in classpath.
* The results of the test are recorded using
* TestRecorder class.
*
* This test should be moved to be on BpmTestBase
* would save the re-implementation of login and logout routines
* DO NOT EMULATE THIS TEST.
*/

public class TimerTest implements TestSet
{

    private WFSession wfSession = null;
    private TestRecorder tr;
    private String serverName = null;
    private String userName = null;
    private String passWord = null;

    public
    void
    runTests(TestRecorder outStreem)
    throws Exception
    {

        try {
            String timerUDAInitValue = "TimerStarted";
            String timerUDAFinalValue = null;
            tr = outStreem;
            logIn();
            Plan testPlan = createTemplate(timerUDAInitValue);
            if(testPlan != null)
            {
                ProcessInstance processInstance = createProcess(testPlan);
                if(processInstance != null){

                    long givenupTime = getCurrentTimeMillis() + 5000;
                    while (((timerUDAFinalValue = processInstance.getDataItem("TimerUDA").getValue() ).equals(timerUDAInitValue))||(timerUDAFinalValue == null))
                    {
                        if(givenupTime < getCurrentTimeMillis()){
                            throw new Exception(" Timer Test -- Waited 5 seconds, process failed to set the UDA variable");
                        }
                        Thread.sleep(100);
                    }
                    logOut();
                    if(timerUDAFinalValue == null)
                    {
                        tr.markFailed("Timer Test", "the ' TimerUDA ' UDA had a null value");
                    }
                    else if(timerUDAFinalValue.equalsIgnoreCase(timerUDAInitValue))
                    {
                       tr.markFailed("Timer Test" , "the ' TimerUDA ' UDA expected to have 'TimerExpired', but actually had '" + timerUDAInitValue + "'");
                    }
                    else
                    {
                        tr.markPassed("Timer Test --  timer successfully fired and set the UDA value");
                    }
                }
            }
        } catch (Exception e) {
            throwWrappedException("Exception caught in main Timer Test", e);
        }

   }

    public
    TimerTest()
    {

    }

    public
    Plan
    createTemplate(String udaInitValue)
        throws Exception
    {
        Plan plan = null;

        try {
            String planName = "TestTimer";
            JavaActionSet actionSet =null;
            JavaAction[] actions = null;
            JavaActionSet actionSet11 =null;
            JavaAction[] actions11 = null;

            plan = WFObjectFactory.getPlan();
            plan.setWFSession(wfSession);
            plan.startEdit();

            plan.addDataItemRef("TimerUDA", "STRING", udaInitValue);

            plan.setName( planName );
            plan.setTitle( planName + " title" );
            plan.setDesc( planName + " description" );
            plan.setPlanIdentifier("Global");
            String script = "setProcessAttribute(\"TimerUDA\" ,\"STRING\",\"TimerExpired\" )";

            TimerAction tAction = WFObjectFactory.getTimerAction(TimerAction.SCRIPT);
            DataItemRef data = plan.addDataItemRef("timeScript","STRING", script);

            tAction.setScriptAction(data.getName());
            TimerDef td = WFObjectFactory.getTimerDef(TimerDef.ABSOLUTE);
            String currentTime = Long.toString(System.currentTimeMillis()+3000);
            DataItemRef data1 = plan.addDataItemRef("time","LONG", currentTime);

            td.setTime(data1.getName());
            td.setName("Test");
            td.addTimerAction(tAction);
            Node startNode = plan.addNode( "Start", Node.TYPE_START );
            int startX = 50;
            int startY = 100;
            startNode.setPosition( new Point( startX, startY ) );

            Node firstActNode = plan.addNode( "ACTIVITY-TIMER", Node.TYPE_ACTIVITY );
            firstActNode.setPosition( new Point( startX + 200, startY ) );
            firstActNode.setRole( "Role" );
            firstActNode.setDesc("ACTIVITY-TIMER");
            firstActNode.addTimer(td);
            plan.addArrow( "START", startNode, firstActNode );

            Node exitNode = plan.addNode( "EXIT", Node.TYPE_EXIT );
            exitNode.setPosition( new Point( startX + 200, startY + 200) );
            plan.addArrow( "DONE", firstActNode, exitNode );
            plan = plan.createProcessDef();
            tr.markPassed("Timer Test -- Successfully created plan " + plan.getId() + " which has a timer in it");
        }
        catch (Exception e) {
            throwWrappedException("Timer Test -- Plan creation failed", e);
        }
        return plan;

    }

    private
    ProcessInstance
    createProcess(Plan plan)
        throws Exception
    {
        ProcessInstance pi = null;
        try {
            pi = plan.createProcessInstance();
            pi.start();
        } catch (Exception e) {
            throwWrappedException("Timer Test -- Process creation failed", e);
        }
        return pi;
    }

    public
    void
    logIn()
    throws Exception
    {
        try {
            String transPortType = tr.getRequiredProperty("TWFTransportType");
            wfSession = WFObjectFactory.getWFSession();
            wfSession.initForApplication(null, tr.getProps());
            tr.markPassed("Timer Test  transPortType ");
            serverName = tr.getRequiredProperty("servername");
            userName = tr.getRequiredProperty("username");
            passWord = tr.getRequiredProperty("password");
            wfSession.logIn(serverName+"Flow", userName, passWord);
        } catch (Exception e) {
            throwWrappedException("Timer Test --  login FAILED on Server : " + serverName + " with  User Name : " + userName + " and Password : " + passWord, e);
        }
    }

    public
    void
    logOut()
    throws Exception
    {
        try {
            wfSession.logOut();
        } catch (Exception e) {
            throwWrappedException("Timer Test --  logout FAILED on Server : " + serverName + " with  User Name : " + userName, e);
        }
        tr.markPassed("Timer Test --  logout  successfully PASSED on Server : " + serverName + " with  User Name : " + userName);
    }

    public
    void
    throwWrappedException(
        String message,
        Exception e)
            throws Exception
    {
        throw new ExceptionWrapper(message, e);
    }

    private
    long
    getCurrentTimeMillis(){
        return System.currentTimeMillis();
    }

}

