// WFAppPackagingTest.java
// This class implements com.fujitsu.iflow.testframe.TestSet interface.
// NOTE: All methods are atomic.
package com.fujitsu.iflowqa.testframe;

import java.awt.Point;
import java.io.File;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Hashtable;
import java.util.Properties;

import com.fujitsu.iflow.common.wfapp.WFAppManifest;
import com.fujitsu.iflow.common.wfapp.WFAppUtil;
import com.fujitsu.iflow.model.util.WFAppInstaller;
import com.fujitsu.iflow.model.util.WFAppPackager;
import com.fujitsu.iflow.model.workflow.Arrow;
import com.fujitsu.iflow.model.workflow.DMS;
import com.fujitsu.iflow.model.workflow.DataItemRef;
import com.fujitsu.iflow.model.workflow.Filter;
import com.fujitsu.iflow.model.workflow.Node;
import com.fujitsu.iflow.model.workflow.Plan;
import com.fujitsu.iflow.model.workflow.WFObjectFactory;
import com.fujitsu.iflow.model.workflow.WFObjectList;
import com.fujitsu.iflow.model.workflow.WFSession;

public class WFAppPackagingTest implements TestSet
{
    static final String AITS_WFAPP_PLAN = "TestWFAppPlan";
    TestRecorder tr;
    Properties serverProperties;
    WFSession wfSession;

    public WFAppPackagingTest() throws Exception
    {
        serverProperties = new Properties();
    }

    public void runTests(TestRecorder ntr) throws Exception
    {
      tr = ntr;
      try
      {
        serverProperties.setProperty("role",tr.getRequiredProperty("role"));

        doLogin();

        getMyPlansTest(tr);

        packageWFApp(tr);

        installWFApp(tr);

        deleteWFAppPlans(tr);

      }
      finally
      {
        doLogout();
      }
    }

    /////////////////////////////////////////test plan///////////////////////////////////////////////////

    void getMyPlansTest(TestRecorder tr) throws Exception
    {
        debug("getMyPlansTest");
        String errorDetail = "";
        boolean idMatched = false;

        try
        {
            long planId = createPlan();
            debug("Plan Id= "+planId);
            serverProperties.setProperty("planid",Long.toString(planId));
        }
        catch(Exception e)
        {
            rethrow("getMyPlansTest", e);
            throw e;
        }
        finally
        {
            ;
        }
    }

    long createPlan() throws Exception
    {
        long planId = -1;
        String planName = AITS_WFAPP_PLAN;
        try
        {
            Plan plan = WFObjectFactory.getPlan();
            plan.setWFSession(wfSession);
            plan.startEdit();
            plan.setName(planName);
            plan.setTitle(planName+" - Title");
            // Start Node.
            Node startNode = plan.addNode("Start", Node.TYPE_START);
            startNode.setPosition(new Point(100, 150));
            // Activity Node1.
            Node node1 = plan.addNode(planName+"-Act1",Node.TYPE_ACTIVITY);
            node1.setPosition(new Point(200, 250));
            node1.setRole(serverProperties.getProperty("role"));
            // UDAs
            DataItemRef diRef1 = plan.addDataItemRef("uda1", DataItemRef.TYPE_STRING, "default");
            DataItemRef diRef2 = plan.addDataItemRef("uda2", DataItemRef.TYPE_BOOLEAN, "true");
            DataItemRef diRef3 = plan.addDataItemRef("uda3", DataItemRef.TYPE_INTEGER, "999");
            DataItemRef diRef4 = plan.addDataItemRef("uda4", DataItemRef.TYPE_LONG, "77777777");
            DataItemRef diRef5 = plan.addDataItemRef("uda5", DataItemRef.TYPE_FLOAT, "888.8");
            DataItemRef diRef6 = plan.addDataItemRef("str", DataItemRef.TYPE_STRING, "test");
            // Exit Node.
            Node exitNode = plan.addNode("Exit", Node.TYPE_EXIT);
            exitNode.setPosition(new Point(300,350));
            // Add Arrows.
            Arrow goArrow = plan.addArrow("Go", startNode, node1);
            Arrow stopArrow = plan.addArrow("Stop", node1, exitNode);
            Plan newPlan = plan.createProcessDef();
            Thread.sleep(500);
            planId = newPlan.getId();
        }
        catch(Exception e)
        {
            rethrow("createPlan", e);
        }
        return planId;
    }

    //////////////////////////////////////////////package workflow application////////////////////////////////////////

    /*
     * This mehtod packages workflow application
     */
    void packageWFApp(TestRecorder tr) throws Exception
    {
        String errorDetail = "";
        boolean started = false;
        try
        {
            long planId = Long.parseLong(serverProperties.getProperty("planid"));
            if(planId > 0)
            {
               long [] planIDs = new long[1];
               planIDs[0] = planId;
               WFAppPackager packager = new WFAppPackager();
               DMS dms =  WFObjectFactory.getDMS(wfSession, wfSession.getUserName(), tr.getRequiredProperty("password"));
               WFAppManifest manifest = packager.getManifest(wfSession,planIDs);
               String packageName = "AITS_TEST_WFAPP_PACKAGE";
               if(packageName != null && packageName.trim().equals("") == false)
                  manifest.setPackageName(packageName);
               String packageRootPath = new File(".").getAbsolutePath() + File.separator + "wfapp";
               File packageRoot = new File(packageRootPath);
               if(packageRoot.exists() == false)
                  packageRoot.mkdirs();
               else
               {
                  packageRoot.delete();
                  WFAppUtil.deleteDir(packageRoot);
                  packageRoot.mkdirs();
               }
               String packagePath = packageRoot.getAbsolutePath() + File.separator + manifest.getPackageName() +
                                    packager.getArchiveStrategy().getFileSuffix();
               String packageFile = packager.packageWFApp(wfSession,dms,packagePath,manifest);
               serverProperties.setProperty("packagePath",packagePath);
               tr.markPassed("Test workflow application packaging successfully");
            }
            else
            {
                tr.markFailed("packageWFApp","Possibly an error");
                throw new Exception("packageWFApp Possibly an error");
            }
        }
        catch(Exception e)
        {
            rethrow("packageWFApp",e);
        }
    }


    ///////////////////////////////////////////Install workflow application////////////////////////////////////////////////
    /*
     * This mehtod installs workflow application package
     */

    void installWFApp(TestRecorder tr) throws Exception
    {
        String errorDetail = "";
        boolean started = false;
        try
        {
            String packagePath = serverProperties.getProperty("packagePath");
            WFAppInstaller installer = new WFAppInstaller();
            WFAppManifest manifest = installer.checkManifest(wfSession,packagePath, new Hashtable());
            DMS dms =  WFObjectFactory.getDMS(wfSession, wfSession.getUserName(), tr.getRequiredProperty("password"));
            manifest.removeServerComponents();
            installer.saveManifest(packagePath, manifest);
            installer.installWFApp(wfSession, dms, packagePath);
            tr.markPassed("Test workflow application installation successfully");
        }
        catch(Exception e)
        {
            rethrow("installWFApp",e);
        }
    }


    ///////////////////////////////////////////delete workflow application plans///////////////////////////////////////////
    /*
     * This mehtod deletes workflow application plans
     */
    private void deleteWFAppPlans(TestRecorder tr) throws Exception
    {
        try
        {
            WFObjectList wfObjectList = WFObjectFactory.getWFObjectList(wfSession);
            wfObjectList.addFilter(WFObjectList.LISTFIELD_PLAN_NAME,"=","'" + AITS_WFAPP_PLAN + "'");
            wfObjectList.openBatchedList(Filter.AllPlans);
            Object[] wiList = wfObjectList.getNextBatch(50);
            while(wiList != null && wiList.length > 0)
            {
                for(int i = 0; i < wiList.length; i++)
                {
                    Plan pl = (Plan) wiList[i];
                    wfSession.deletePlan(pl.getId());
                }
                wiList = wfObjectList.getNextBatch(50);
            }
        }
        catch(Exception e)
        {
            rethrow("deleteWFAppPlans()", e);
        }
    }

   private void doLogin() throws Exception
    {
        try
        {
            wfSession = WFObjectFactory.getWFSession();
            wfSession.initForApplication(null, tr.getProps());
            wfSession.logIn(tr.getRequiredProperty("servername")+"Flow",
                        tr.getRequiredProperty("username"),
                        tr.getRequiredProperty("password"));
        }
        catch(Exception e)
        {
            rethrow("doLogin", e);
        }
    }


    private void doLogout()throws Exception
    {
        debug("doLogout()");
        try
        {
            wfSession.logOut();
        }
        catch(Exception e)
        {
            rethrow("doLogout",e);
        }
    }

    // this converts an exception stack trace to a string.  Seems like
    // the wrong thing to be doing, since the TestRecorder can be made to
    // print out stack traces.  The exceptoin objects already has the
    // stack trace within it, so why convert it to a string???????
    // Consider removing this.
    String stringify(Exception e)
    {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        e.printStackTrace(pw);
        return sw.getBuffer().toString();
    }

    void debug(String msg)
    {
        ;
    }

    void rethrow(String msg, Exception e) throws Exception
    {
        throw new ExceptionWrapper(msg,e);
    }

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

}
