package com.fujitsu.iflowqa.testframe;

import java.awt.Point;

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.WFObjectFactory;
import com.fujitsu.iflow.model.workflow.WFSession;

/*
 * This class is to test the Action Agent. The name of the Agent is TestFrameAgent.
 * Check the availability of AgentConfig file.
 * Create a plan with one regular activity node assigned to "TestFrameAgent".
 * Start The Process. Wait a sec to check the state of the Process
 * Process should be in close state. If not will try two more time.
 * If process is not completed report error
 */
public class ActionAgentTest implements TestSet {

    private static String AGENT_NAME = "@TestFrameAgent";
    private WFSession wfSession = null;
    private TestRecorder tRecorder;
     /*
     * Zero argument constructor.
     */
    public ActionAgentTest() {
    }

    /*
     * This method runs the rest.
     */
    public void runTests(TestRecorder tRecorder) throws Exception
    {
        this.tRecorder = tRecorder;
        logIn();
        try {
            // the fist argument from the tRecorder will be the xpdl file name.
            Plan agent_plan = createPlan();
            ProcessInstance pi = createProcess(agent_plan);
            long piId = pi.getId();
            startProcess(pi);
            String msg = "Waiting for Process id:" + piId + " to close.";
            debug(msg);
            SafeSleep sleeper = new SafeSleep(msg);
            while(getProcessState(piId) != pi.STATE_CLOSED) {
                sleeper.nap();
            }
            tRecorder.markPassed("ActionAgentTest -- Test case passed");
        } finally {
            logOut();
        }
    }

     /**
    * 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.ActionAgentTest";
        TestDriver.main(newArgs);
    }

    /*
     * This method creates the template
     */
    private
    Plan
    createPlan()
    throws Exception
    {
           Plan plan = null;

       try {
            String planName = "iflowTest_Agent";

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

            plan.setName( planName );
            plan.setTitle( planName + " title" );
            plan.setDesc( planName + " description" );
            plan.setPlanIdentifier("Global");

            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-AGENT", Node.TYPE_ACTIVITY );
            firstActNode.setPosition( new Point( startX + 200, startY ) );
            firstActNode.setRole(AGENT_NAME);
            firstActNode.setDesc("ACTIVITY-AGENT");
            startNode.addArrow( "START", firstActNode );

            Node exitNode = plan.addNode( "EXIT", Node.TYPE_EXIT );
            exitNode.setPosition( new Point( startX + 200, startY + 200) );
            firstActNode.addArrow( "DONE", exitNode );
            plan = plan.createProcessDef();
            tRecorder.markPassed("ActionAgentTest -- Successfully plan created with ID :" + plan.getId());

        }catch (Exception e) {
            logException("ActionAgentTest.createPlan() - Plan creation failed" , e);
        }
        return plan;
    }

    /*
     * Crete Process Instance
     */
    private
    ProcessInstance
    createProcess(
        Plan pd) throws Exception
    {
        ProcessInstance pi = null;
        try {
            pi = pd.createProcessInstance();
            tRecorder.markPassed("ActionAgentTest -- Successfully ProcessInstance created with ID :" + pi.getId());

        }catch (Exception e) {
            logException("ActionAgentTest.createProcess() - Process creation failed for paln:" + pd.getId() , e);
        }

        return pi;
    }

    private
    void
    startProcess(
        ProcessInstance pi)throws Exception
    {
        try {
            pi.start();
            tRecorder.markPassed("ActionAgentTest -- Successfully ProcessInstance started with ID :" + pi.getId());
        }
        catch(Exception e){
            logException("ActionAgentTest.startProcess() - Process start failed for ProcessInstance:" + pi.getId() , e);
        }
    }

    private
    int
    getProcessState(
        long piId) throws Exception
    {
        int state = -1;
        try {
            ProcessInstance pi = WFObjectFactory.getProcessInstance(piId, wfSession);
            tRecorder.markPassed("ActionAgentTest -- Successfully retrieved ProcessInstance state with ID :" + pi.getId());
            state = pi.getState();
        }catch(Exception e){
            logException("ActionAgentTest.getProcessState() - Process start failed for ProcessInstance:" + piId , e);
        }
        return state;
    }

     /*
     * Login
     */
    private
    void
    logIn()
        throws Exception
    {
        debug("logIn(server=" + tRecorder.getRequiredProperty("servername") +
                  ", user=" + tRecorder.getRequiredProperty("username") + ")");
        try {
            String transPortType = tRecorder.getRequiredProperty("TWFTransportType");
            wfSession = WFObjectFactory.getWFAdminSession();
            wfSession.initForApplication(null, tRecorder.getProps());
            wfSession.logIn(tRecorder.getRequiredProperty("servername") +"Flow",
                            tRecorder.getRequiredProperty("username"),
                            tRecorder.getRequiredProperty("password"));
            tRecorder.markPassed("ActionAgentTest -- Successfully Login");
        }
        catch (Exception e) {
            logException("ActionAgentTest.login() Failed to Login", e);
        }
    }

    /*
     * LogOut
     */
    private
    void
    logOut()
        throws Exception
    {
        debug("logOut()");
        try {
            wfSession.logOut();
        } catch(Exception e) {
            logException("ActionAgentTest.logOut() Failed to Logout ", e);
        }
    }

    private
    void
    debug(String msg)
    {
        // uncomment if you want debug output
        // tRecorder.log(msg);
    }

    private
    void
    logException(
        String message,
        Exception e)
        throws Exception
    {
        tRecorder.log(message);
        throw e;
    }


}
