package com.fujitsu.iflowqa.testframe;

// iflow classes.
import java.util.Random;
import java.util.Vector;

import com.fujitsu.iflow.model.workflow.DataItem;
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.ProcessInstance;
import com.fujitsu.iflow.model.workflow.WFObjectFactory;
import com.fujitsu.iflow.model.workflow.WFObjectList;
import com.fujitsu.iflow.model.workflow.WorkItem;

// jdk classes.

public class VotingXPDLTest extends BPMTestBase implements TestSet {

    /*
     * Zero argument constructor.
     */
    public VotingXPDLTest() {
    }

    /*
     * This method runs the rest.
     */
    public void runTests(TestRecorder recorder) throws Exception {
        init(recorder);

        debug("Voting XPDL runTests()");
        String filename = null;
        long piId = -1;

        try {
            login();
            // the fist argument from the tr will be the xpdl file name.
            String[] commandLineArgs = tr.getCommandLineArgs();
            filename = commandLineArgs[1];
            Plan plan = createPlanFromXPDL(filename);
            tr.log("Plan " + lastImportedPlan + " : " + " VotingXPDLTest started for "
                    + filename);
            ProcessInstance pi = createProcess(plan);
            if (!handleWorkItems(pi)) {
                return;
            }
            if (!checkNegativeTestCase(pi)) {
                checkResultUDA(pi);
            }
        } catch (Exception e) {
            throw new ExceptionWrapper("Exception caught in main test level", e);
        } finally {
            logOutWithoutException();
        }
    }

    /*
     * This mehtod handles all the workitems for the give user and on the given
     * process.
     */
    private boolean handleWorkItems(ProcessInstance pi) throws Exception {
        debug("handleWorkItems()");
        Random randNo = new Random();

        try {

            int noWorkListGuard = 300;

            while (true) {

                if (pi.getState() == pi.STATE_CLOSED) {
                    return true;
                }

                WFObjectList wfol = WFObjectFactory.getWFObjectList(wfSession);
                wfol.addFilter(WFObjectList.LISTFIELD_PROCESSINSTANCE_ID, "=",
                        "'" + pi.getId() + "'");
                wfol.openBatchedList(Filter.MyActiveWorkItems);
                Object[] workItemList = wfol.getNextBatch(0, 99);

                if ((workItemList == null) || (workItemList.length == 0)) {
                    if (noWorkListGuard-- < 0) {
                        //To test negative test cases
                        DataItem expDi = pi.getDataItem(PEXCEPTION_UDA);
                        if (expDi != null) {
                            checkNegativeTestCase(pi);
                        }
                        return false;
                        //throw new Exception("Timeout waiting 30 seconds for
                        // workitem to appear.");
                    }
                    Thread.sleep(100);
                    if (pi.getState() == pi.STATE_CLOSED) {
                        return true;
                    }
                    continue;
                }

                WorkItem workItem = (WorkItem) workItemList[randNo
                        .nextInt(workItemList.length)];
                com.fujitsu.iflow.model.workflow.NodeInstance nInstance = workItem
                        .getNodeInstance();

                if (nInstance.getType() == Node.TYPE_VOTING_ACTIVITY) {
                    String role = nInstance.getRole();
                    DataItem di = pi.getDataItem("VotingList");
                    String votingList = di.getValue();
                    String[] usersList = splitString(votingList);

                    for (int i = 0; i < usersList.length; i++) {

                        String aUser = usersList[i];
                        FlowPath test = new FlowPath();
                        int index = aUser.indexOf(':');
                        String uName = aUser.substring(0, index);
                        int end = aUser.length();
                        tr.log("Plan " + lastImportedPlan + " : " + "Token :" + aUser);
                        if (uName.equalsIgnoreCase("stop")) {
                            pi.startEdit();
                            java.util.Properties props = new java.util.Properties();
                            props.put("__DriverControlLimit", usersList[i]
                                    .substring(index + 1, end));
                            props.put("__DriverControl", "stop");
                            pi.setDataItemValues(props);
                            pi.commitEdit();
                            tr.log("Plan " + lastImportedPlan + " : " + "After Commit");

                        } else {
                            test.logInAndHandleWorkItems(tr, uName, uName, pi,
                                    aUser.substring(index + 1, end));
                        }
                    }
                    Thread.sleep(200);
                } else {
                    FlowPath test = new FlowPath();
                    String uName = tr.getRequiredProperty("username");
                    String uPass = tr.getRequiredProperty("password");
                    test.logInAndHandleWorkItems(tr, uName, uPass, pi,
                            "default");
                }
            }
        } catch (Exception e) {
            tr.log("Plan " + lastImportedPlan + " : " + "in Handle" + e.getMessage());
            checkNegativeTestCase(pi);
            throw new ExceptionWrapper(
                    "handleWorkItems() - Possibly because of WorkItem.makeChoice()",
                    e);
        }
    }

    private static String[] splitString(String commaList) {
        if (commaList == null || commaList.length() == 0) {
            return new String[0];
        }
        Vector v = new Vector();
        int startPos = 0;
        int pos = commaList.indexOf(',');
        while (pos >= 0 && startPos < commaList.length()) {
            v.add(commaList.substring(startPos, pos));
            startPos = pos + 1;
            pos = commaList.indexOf(',', startPos);
        }
        if (startPos < commaList.length()) {
            v.add(commaList.substring(startPos));
        }
        int num = v.size();
        String[] result = new String[num];
        for (int i = 0; i < num; i++) {
            result[i] = (String) v.elementAt(i);
        }
        return result;
    }
}
