/*******************************************************************************
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *******************************************************************************/
package org.ofbiz.workflow;

import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.transaction.Transaction;
import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.StringUtil;
import org.ofbiz.base.util.UtilDateTime;
import org.ofbiz.base.util.UtilMisc;
import org.ofbiz.entity.GenericEntityException;
import org.ofbiz.entity.GenericValue;
import org.ofbiz.entity.transaction.GenericTransactionException;
import org.ofbiz.entity.transaction.TransactionUtil;
import org.ofbiz.service.GenericRequester;
import org.ofbiz.service.GenericResultWaiter;
import org.ofbiz.service.GenericServiceException;
import org.ofbiz.service.ModelService;
import org.ofbiz.service.ServiceDispatcher;
import org.ofbiz.service.engine.AbstractEngine;
import org.ofbiz.service.job.AbstractJob;
import org.ofbiz.service.job.Job;
import org.ofbiz.service.job.JobManagerException;

/**
 * WorkflowEngine - Workflow Service Engine
 */
public class WorkflowEngine extends AbstractEngine {

    public static final String module = WorkflowEngine.class.getName();

    public WorkflowEngine(ServiceDispatcher dispatcher) {
        super(dispatcher);
    }

    /**
     * @see org.ofbiz.service.engine.GenericEngine#runSync(java.lang.String, org.ofbiz.service.ModelService, java.util.Map)
     */
    public Map<String, Object> runSync(String localName, ModelService modelService, Map<String, Object> context) throws GenericServiceException {
        GenericResultWaiter waiter = new GenericResultWaiter();
        runAsync(localName, modelService, context, waiter, false);
        return waiter.waitForResult();
    }

    /**
     * @see org.ofbiz.service.engine.GenericEngine#runSyncIgnore(java.lang.String, org.ofbiz.service.ModelService, java.util.Map)
     */
    public void runSyncIgnore(String localName, ModelService modelService, Map<String, Object> context) throws GenericServiceException {
        runAsync(localName, modelService, context, null, false);
    }

    /**
     * @see org.ofbiz.service.engine.GenericEngine#runAsync(java.lang.String, org.ofbiz.service.ModelService, java.util.Map, boolean)
     */
    public void runAsync(String localName, ModelService modelService, Map<String, Object> context, boolean persist) throws GenericServiceException {
        runAsync(localName, modelService, context, null, persist);
    }

    /**
     * @see org.ofbiz.service.engine.GenericEngine#runAsync(java.lang.String, org.ofbiz.service.ModelService, java.util.Map, org.ofbiz.service.GenericRequester, boolean)
     */
    public void runAsync(String localName, ModelService modelService, Map<String, Object> context, GenericRequester requester, boolean persist) throws GenericServiceException {
        Transaction parentTrans = null;
        boolean beganTransaction = false;
        try {
            try {
                parentTrans = TransactionUtil.suspend();
                beganTransaction = TransactionUtil.begin();
                //Debug.logInfo("Suspended transaction; began new: " + beganTransaction, module);
            } catch (GenericTransactionException e) {
                Debug.logError(e, "Cannot begin nested transaction: " + e.getMessage(), module);
            }

            // Build the requester
            WfRequester req = null;
            try {
                req = WfFactory.getWfRequester();
            } catch (WfException e) {
                try {
                    TransactionUtil.rollback(beganTransaction, "Error getting Workflow Requester", e);
                } catch (GenericTransactionException gte) {
                    Debug.logError(gte, "Unable to rollback nested exception.", module);
                }
                throw new GenericServiceException(e.getMessage(), e);
            }

            // Get the package and process ID::VERSION
            String location = this.getLocation(modelService);
            String invoke = modelService.invoke;
            String packageId = this.getSplitPosition(location, 0);
            String packageVersion = this.getSplitPosition(location, 1);
            String processId = this.getSplitPosition(invoke, 0);
            String processVersion = this.getSplitPosition(invoke, 1);

            // Build the process manager
            WfProcessMgr mgr = null;
            try {
                mgr = WfFactory.getWfProcessMgr(dispatcher.getDelegator(), packageId, packageVersion, processId, processVersion);
            } catch (WfException e) {
                String errMsg = "Process manager error";
                Debug.logError(e, errMsg, module);
                try {
                    TransactionUtil.rollback(beganTransaction, errMsg, e);
                } catch (GenericTransactionException gte) {
                    Debug.logError(gte, "Unable to rollback nested exception.", module);
                }
                throw new GenericServiceException(e.getMessage(), e);
            } catch (Exception e) {
                Debug.logError(e, "Un-handled process manager error", module);
                throw new GenericServiceException(e.getMessage(), e);
            }

            // Create the process
            WfProcess process = null;
            try {
                process = mgr.createProcess(req);
            } catch (NotEnabled ne) {
                try {
                    TransactionUtil.rollback(beganTransaction, "Error in create workflow process: Not Enabled", ne);
                } catch (GenericTransactionException gte) {
                    Debug.logError(gte, "Unable to rollback nested exception.", module);
                }
                throw new GenericServiceException(ne.getMessage(), ne);
            } catch (InvalidRequester ir) {
                try {
                    TransactionUtil.rollback(beganTransaction, "Error in create workflow process: Invalid Requester", ir);
                } catch (GenericTransactionException gte) {
                    Debug.logError(gte, "Unable to rollback nested exception.", module);
                }
                throw new GenericServiceException(ir.getMessage(), ir);
            } catch (RequesterRequired rr) {
                try {
                    TransactionUtil.rollback(beganTransaction, "Error in create workflow process: Requester Required", rr);
                } catch (GenericTransactionException gte) {
                    Debug.logError(gte, "Unable to rollback nested exception.", module);
                }
                throw new GenericServiceException(rr.getMessage(), rr);
            } catch (WfException wfe) {
                try {
                    TransactionUtil.rollback(beganTransaction, "Error in create workflow process: general workflow error error", wfe);
                } catch (GenericTransactionException gte) {
                    Debug.logError(gte, "Unable to rollback nested exception.", module);
                }
                throw new GenericServiceException(wfe.getMessage(), wfe);
            } catch (Exception e) {
                Debug.logError(e, "Un-handled process exception", module);
                throw new GenericServiceException(e.getMessage(), e);
            }

            // Assign the owner of the process
            GenericValue userLogin = null;
            if (context.containsKey("userLogin")) {
                userLogin = (GenericValue) context.remove("userLogin");
                try {
                    Map<String, Object> fields = UtilMisc.toMap("partyId", userLogin.getString("partyId"),
                            "roleTypeId", "WF_OWNER", "workEffortId", process.runtimeKey(),
                            "fromDate", UtilDateTime.nowTimestamp());

                    try {
                        GenericValue wepa = dispatcher.getDelegator().makeValue("WorkEffortPartyAssignment", fields);
                        dispatcher.getDelegator().create(wepa);
                    } catch (GenericEntityException e) {
                        String errMsg = "Cannot set ownership of workflow";
                        try {
                            TransactionUtil.rollback(beganTransaction, errMsg, e);
                        } catch (GenericTransactionException gte) {
                            Debug.logError(gte, "Unable to rollback nested exception.", module);
                        }
                        throw new GenericServiceException(errMsg, e);
                    }
                } catch (WfException we) {
                    String errMsg = "Cannot get the workflow process runtime key";
                    try {
                        TransactionUtil.rollback(beganTransaction, errMsg, we);
                    } catch (GenericTransactionException gte) {
                        Debug.logError(gte, "Unable to rollback nested exception.", module);
                    }
                    throw new GenericServiceException(errMsg);
                }
            }

            // Grab the locale from the context
            Locale locale = (Locale) context.remove("locale");

            // Grab the starting activityId from the context
            String startActivityId = (String) context.remove("startWithActivityId");

            // Register the process and set the workflow owner
            try {
                req.registerProcess(process, context, requester);
                if (userLogin != null) {
                    Map<String, Object> pContext = process.processContext();
                    pContext.put("workflowOwnerId", userLogin.getString("userLoginId"));
                    process.setProcessContext(pContext);
                }
            } catch (WfException wfe) {
                try {
                    TransactionUtil.rollback(beganTransaction, wfe.getMessage(), wfe);
                } catch (GenericTransactionException gte) {
                    Debug.logError(gte, "Unable to rollback nested exception.", module);
                }
                throw new GenericServiceException(wfe.getMessage(), wfe);
            }

            // Set the initial locale - (in context)
            if (locale != null) {
                try {
                    Map<String, Object> pContext = process.processContext();
                    pContext.put("initialLocale", locale);
                    process.setProcessContext(pContext);
                } catch (WfException wfe) {
                    try {
                        TransactionUtil.rollback(beganTransaction, wfe.getMessage(), wfe);
                    } catch (GenericTransactionException gte) {
                        Debug.logError(gte, "Unable to rollback nested exception.", module);
                    }
                    throw new GenericServiceException(wfe.getMessage(), wfe);
                }
            }

            // Use the WorkflowRunner to start the workflow in a new thread
            try {
                Job job = new WorkflowRunner(process, requester, startActivityId);
                if (Debug.verboseOn()) Debug.logVerbose("Created WorkflowRunner: " + job, module);
                dispatcher.getJobManager().runJob(job);
            } catch (JobManagerException je) {
                try {
                    TransactionUtil.rollback(beganTransaction, je.getMessage(), je);
                } catch (GenericTransactionException gte) {
                    Debug.logError(gte, "Unable to rollback nested exception.", module);
                }
                throw new GenericServiceException(je.getMessage(), je);
            }

            try {
                TransactionUtil.commit(beganTransaction);
            } catch (GenericTransactionException e) {
                Debug.logError(e, "Cannot commit nested transaction: " + e.getMessage(), module);
            }
        } finally {
            // Resume the parent transaction
            if (parentTrans != null) {
                try {
                    TransactionUtil.resume(parentTrans);
                    //Debug.logInfo("Resumed the parent transaction.", module);
                } catch (GenericTransactionException e) {
                    throw new GenericServiceException("Could not resume transaction: " + e.toString(), e);
                }
            }
        }
    }

    private String getSplitPosition(String splitString, int position) {
        if (splitString.indexOf("::") == -1) {
            if (position == 0)
                return splitString;
            if (position == 1)
                return null;
        }
        List<String> splitList = StringUtil.split(splitString, "::");
        return splitList.get(position);
    }
}

/** Workflow Runner class runs inside its own thread using the Scheduler API */
@SuppressWarnings("serial")
class WorkflowRunner extends AbstractJob {

    GenericRequester requester;
    WfProcess process;
    String startActivityId;

    WorkflowRunner(WfProcess process, GenericRequester requester, String startActivityId) {
        super(process.toString() + "." + System.currentTimeMillis(), process.toString());
        this.process = process;
        this.requester = requester;
        this.startActivityId = startActivityId;
        runtime = new Date().getTime();
    }

    protected void finish() {
        runtime = -1;
    }

    @Override
    public void exec() {
        try {
            if (startActivityId != null)
                process.start(startActivityId);
            else
                process.start();
        } catch (Exception e) {
            Debug.logError(e, module);
            if (requester != null)
                requester.receiveResult(null);
        }
        finish();
    }
}

