package com.horizon.wf.example;

import com.horizon.wf.bean.WorkParaBean;
import com.horizon.wf.core.rule.BaseRuleImpl;
import com.horizon.wf.core.rule.IBaseRule;
import com.horizon.wf.core.runtime.RunningData;
import com.horizon.wf.core.track.json.impl.ITrackJson;
import com.horizon.wf.definition.pub.IFlowNode;
import com.horizon.wf.definition.pub.node.INodeException;
import com.horizon.wf.definition.pub.node.INodePara;
import com.horizon.wf.definition.pub.node.INodeRouter;
import com.horizon.wf.entity.db.DBTrack;
import com.horizon.wf.entity.db.DBWork;
import com.horizon.wf.entity.user.IRunUser;
import com.horizon.wf.global.StaticVar;
import com.horizon.wf.global.StaticVarExtend;
import com.horizon.wf.tools.CStrUtil;

import java.util.List;
import java.util.Map;

/**
 * Example of a description of an interface implementation class
 * Must inherit from existing class -> com.horizon.wf.core.rule.BaseRuleImpl
 */
public class Example extends BaseRuleImpl implements IBaseRule {

    /**
     * Pecific implementations, refer to the description in the following method, all implementations are similar in structure.
     * Only custom implementations of the exception handling interface do not pass runningdata.
     * The only difference between the interfaces is the extra parameters that are passed in, most of which can be retrieved from runningdata.
     * In order to facilitate the implementation of the interface, the system passes in some additional parameters that are thought to be used.
     * @return
     */
    @Override
    public boolean executeRule() {

        return false;
    }

    /**
     * Inner circular node
     * If the frontend does not pass in a handler, then determine if there is an interface class
     * @return
     */
    private boolean doProgressively(){
        // Get the core data object from the engine (you can get it from this object if the interface doesn't pass in additional data you need).
        RunningData runningdata = getRunningdata();
        DBWork work = (DBWork)getParameter(StaticVarExtend.Parameter_DBWork);// runningdata.getWork());
        WorkParaBean paraBean =(WorkParaBean)getParameter(StaticVarExtend.Parameter_WorkParaBean);// Setting up front and backend objects to interfaces
        IFlowNode curNode = (IFlowNode)getParameter(StaticVarExtend.Parameter_Current_IFlowNode);// Step-by-step approval nodes
        IRunUser user = (IRunUser) getParameter(StaticVarExtend.Parameter_RunUser);// current operator
        String userid = (String)getParameter(StaticVarExtend.Parameter_Progressive_Userid);// Person ids submitted to the cascading approval node

        // Return the next processor id to the engine via the 'setResult("")' method

        // Return ture, the engine will get the processor from the returned result, false will be ignored.
        return true;
    }

    /**
     * Merge gateway Merge processing
     * @return
     */
    private boolean doGatewayMerger(){
        // Get the core data object from the engine (you can get it from this object if the interface doesn't pass in additional data you need).
        RunningData runningdata = getRunningdata();

        WorkParaBean paraBean = (WorkParaBean)getParameter(StaticVarExtend.Parameter_WorkParaBean);
        IFlowNode curNode = (IFlowNode)getParameter(StaticVarExtend.Parameter_GateWay_IFlowNode);// current node
        // List of all branches that need to reach the merge gateway
        List<ITrackJson> lstTrack = (List<ITrackJson>) getParameter(StaticVarExtend.Parameter_GateWay_Alltracks);// Set all branch path information to interface 'rd.getAllTrackNeedToGateway(this)'
        DBTrack track = (DBTrack)getParameter(StaticVarExtend.Parameter_DBTrack);// rd.getCurTrack());
        DBWork work = (DBWork)getParameter(StaticVarExtend.Parameter_DBWork);// rd.getWork());
        IRunUser user = (IRunUser)getParameter(StaticVarExtend.Parameter_RunUser);// rd.getCurUser());
        // If there is a branch that needs to be undone, use the 'setResult("")' method to return the path id of the branch that needs to be undone to the engine.

        // Returns whether leaving is allowed true Allowed to leave false Not allowed to leave
        return true;
    }

    /**
     * Customization in Multiplayer Parallel Node Departure Rules
     * Call entry: com.horizon.wf.expand.node.NodeMultiImpl#doNormal
     * @return
     */
    private boolean doNodeMultilLeave(){
        // Get the core data object from the engine (you can get it from this object if the interface doesn't pass in additional data you need).
        RunningData runningdata = getRunningdata();

        WorkParaBean paraBean = (WorkParaBean)getParameter(StaticVarExtend.Parameter_WorkParaBean);
        IFlowNode curNode = (IFlowNode)getParameter(StaticVarExtend.Parameter_Current_IFlowNode);//当前节点

        // Returns whether leaving is allowed true Allowed to leave false Not allowed to leave
        return true;
    }

    /**
     * Definition implementation in the merged node activation method
     *
     * @return
     */
    private boolean doMergerEntryType(){
        // Get the core data object from the engine (you can get it from this object if the interface doesn't pass in additional data you need).
        RunningData runningdata = getRunningdata();

        WorkParaBean paraBean = (WorkParaBean)getParameter(StaticVarExtend.Parameter_WorkParaBean);
        IFlowNode curNode = (IFlowNode)getParameter(StaticVarExtend.Parameter_Current_IFlowNode);// current node
        IFlowNode mergerNode = (IFlowNode)getParameter(StaticVarExtend.Parameter_Merger_IFlowNode);// entry node

        int allTrackNum = (Integer)getParameter("AllTrackNum"); // Number of all branches to be reached
        int reachedNum = (Integer)getParameter("ReachedTrackNum"); // Number of branches reached

        // Returns whether leaving is allowed true Allowed to leave false Not allowed to leave
        return true;
    }
    /**
     * Custom implementations in the way to leave a merged node
     * Call entry: com.horizon.wf.expand.node.NodeMergerImpl#checkMergerNodeLeaveRule
     * @return
     */
    private boolean doMergerLeaveType(){
        // Get the core data object from the engine (you can get it from this object if the interface doesn't pass in additional data you need).
        RunningData runningdata = getRunningdata();

        WorkParaBean paraBean = (WorkParaBean)getParameter(StaticVarExtend.Parameter_WorkParaBean);
        IFlowNode curNode = (IFlowNode)getParameter(StaticVarExtend.Parameter_Current_IFlowNode);//当前节点
        IFlowNode mergerNode = (IFlowNode)getParameter(StaticVarExtend.Parameter_Merger_IFlowNode);

        // Returns whether leaving is allowed true Allowed to leave false Not allowed to leave
        return true;
    }


    /**
     * Exception Handling Interface Implementation Sample Code
     * Call entry: com.horizon.wf.action.common.ActionCommon#dealException
     * @return
     */
    private boolean doException(){
        // 1.Parameter object passed in when the engine is called.
        WorkParaBean paraBean = (WorkParaBean) getParameter(StaticVarExtend.Parameter_WorkParaBean);
        // 2.Current instance object
        DBWork work = (DBWork) getParameter(StaticVarExtend.Parameter_DBWork);
        // 3.Current path object
        DBTrack track = (DBTrack) getParameter(StaticVarExtend.Parameter_DBTrack);
        // 4.Current Exception Definition Object
        INodeException e = (INodeException) getParameter(StaticVarExtend.Parameter_Exception_INodeException);
        // 5.Exception handling contents

        // Returns true, the exception is canceled.
        // If it returns false, you can use setResult to specify a system default: setResult("2"); or you can leave it as it is if it returns true.
        // 2 = jump, 3 = hang, 4 = abort, other values are ignored by the system
        return true;
    }

    /**
     * Sample code for an extended implementation of node entry (only used in its few cases)
     * Call entry: com.horizon.wf.rule.defa.core.EntryRuleDefault#actionInterface
     * @return
     */
    private boolean doNodeEntry(){
        // Get the core data object from the engine (you can get it from this object if the interface doesn't pass in additional data you need).
        RunningData runningdata = getRunningdata();
        // The node object to enter
        IFlowNode entryNode = (IFlowNode) getParameter(StaticVar.Para_EntryRules_IXmlNode);
        // Route pointing to the node to be accessed
        INodeRouter fromRouter =(INodeRouter) getParameter(StaticVar.Para_EntryRules_IXmlRouter);
        // Node entry method, 1 entry by routing direction, 2=returned entry, 3=jumped entry
        int leaveType = (Integer)getParameter(StaticVar.Para_EntryRules_LeaveType);
        // The parameter to be used when returning, usually the path id of the node to be returned.
        String oldTrackid =(String)getParameter(StaticVar.Para_EntryRules_OldTrackidForReject);

        // Code to be executed

        // Return true to indicate that the node is allowed to enter, false to indicate that it is not allowed to enter.
        return true;
    }
    /**
     * Sample code for an extended implementation of node leave (only used in its few cases)
     * Call entry: com.horizon.wf.rule.defa.core.LeaveRuleDefault
     * @return
     */
    private boolean doNodeLeave(){
        // Get the core data object from the engine (you can get it from this object if the interface doesn't pass in additional data you need).
        RunningData runningdata = getRunningdata();
        // Current node object (leaving only the current node)
        IFlowNode curNode = (IFlowNode) getParameter(StaticVar.Para_LeaveRules_IXmlNode);

        // Code to be executed

        // For example, to realize the function of wanting to make changes to node parameters when the node leaves is as follows.
        List<INodePara> paraList = runningdata.getCurFlowNode().getAllNodePara();
        INodePara para = paraList.get(0);

        String initValue = para.getInitialValue();
        // Get the data for the current node parameter
        String oldValue = runningdata.getThisNodeParaValue(para.getParaId());
        int tmp = 0;
        if(CStrUtil.isNull(oldValue)){
            tmp = Integer.parseInt(initValue);
        }
        else{
            tmp = Integer.parseInt(oldValue);
        }
        tmp += 1;
        // Assign a value to the current node parameter
        runningdata.setThisNodeParaValue(para.getParaId(),""+tmp);
        // ----- code above, for reference only ----------
        // Return true to indicate that the node is allowed to leave, false to indicate that it is not allowed to leave.
        return true;
    }

    /**
     * Sample code for the node event handling implementation class
     * Call entry: com.horizon.wf.rule.event.EventUtil#excuteEvents
     * @return
     */
    private boolean doNodeEvent(){
        // Get the core data object from the engine (you can get it from this object if the interface doesn't pass in additional data you need).
        RunningData runningdata = getRunningdata();
        // Event Handler Class Additional Passed Parameters
        // 1.The node object that executes the event
        IFlowNode eventNode = (IFlowNode) getParameter(StaticVarExtend.Parameter_IFlowNode);
        // 2.Current Node Object
        IFlowNode curNode = (IFlowNode)getParameter(StaticVarExtend.Parameter_Current_IFlowNode);
        // 3.Parameter object passed in when the engine is called.
        WorkParaBean paraBean = (WorkParaBean)getParameter(StaticVarExtend.Parameter_WorkParaBean);
        // 4.Current instance object
        DBWork work = (DBWork)getParameter(StaticVarExtend.Parameter_DBWork);
        // 5.Current executor objects
        IRunUser user = (IRunUser) getParameter(StaticVarExtend.Parameter_RunUser);
        // 6.Current path object
        DBTrack track = (DBTrack)getParameter(StaticVarExtend.Parameter_DBTrack);
        // 7.If you need the engine to save the SQL data, please put it into this map (key=SQL, value=List is the corresponding parameter in SQL).
        Map<String, List<Object>> dataMap = (Map<String, List<Object>>) getParameter(StaticVarExtend.Parameter_SaveMap);
        // 8.Event Type
        String eventType = (String)getParameter("eventType");
        // 9.What the event actually performs

        // 10.Return true means the execution is successful, the engine obtains the data that needs to be saved from the dataMap in step 7, and the engine continues to execute.
        // Returning false means the execution failed, and the engine will decide whether to continue or not depending on the type of event.
        return true;
    }

    /**
     * Entry extension class for event nodes
     * @return
     */
    private boolean doEventNodeEntry(){
        // Get the core data object from the engine (you can get it from this object if the interface doesn't pass in additional data you need).
        RunningData runningdata = getRunningdata();

        WorkParaBean paraBean = (WorkParaBean)getParameter(StaticVarExtend.Parameter_WorkParaBean);// Setting up front and backend objects to interfaces
        DBWork work = (DBWork) getParameter(StaticVarExtend.Parameter_DBWork);
        IRunUser user = (IRunUser)getParameter(StaticVarExtend.Parameter_RunUser);
        DBTrack track = (DBTrack)getParameter(StaticVarExtend.Parameter_DBTrack);
        // If you need the engine to save the data, put it in a savemap, and the engine will get it from there.
        Map<String, List<Object>> saveMap = (Map<String,List<Object>>)getParameter(StaticVarExtend.Parameter_SaveMap);

        // Return true to allow the event node to enter, false to disallow it.
        return true;
    }

    /**
     * Custom Interface Implementation Demonstration Code for Getting Handlers
     * Call entry: com.horizon.wf.rule.defa.core.EntryRuleDefault#getUserFromCustom
     * @return
     */
    private boolean doCustomUser(){
        // Get the core data object from the engine (you can get it from this object if the interface doesn't pass in additional data you need).
        RunningData runningdata = getRunningdata();
        // The following parameters are additional objects that are passed in when getting the processor.
        // 1.When the engine is called, the parameter object is passed in.
        WorkParaBean paraBean = (WorkParaBean)getParameter(StaticVarExtend.Parameter_WorkParaBean);
        // 2.Data set in the process definition used to get customized processors
        String customer = (String)getParameter(StaticVarExtend.Parameter_CustomeUser_Para);
        // 3.Get the node definition object for the handler
        IFlowNode flowNode = (IFlowNode) getParameter(StaticVarExtend.Parameter_CustomeUser_IFlowNode);
        // 4.Obtained processor ID
        String userId = "";
        // 5.Acquired handler returns
        setResult(userId);
        // 6.return
        // True means the fetch was successful, the engine will get the result from the return value set in step 5 false, the engine ignores the result.
        return true;
    }


    /**
     * Sample Code for Routing Conditional Judgment Interface Implementation
     * @return
     */
    private boolean doRouter(){
        // Get the core data object from the engine (you can get it from this object if the interface doesn't pass in additional data you need).
        RunningData runningdata = getRunningdata();
        // The following two parameters are additional objects passed to the engine for use by the current interface implementation when this interface class is called.
        // 1.Get the route definition object ,through the router can get the data defined in the process definition .
        INodeRouter router = (INodeRouter)getParameter(StaticVarExtend.Para_RouterRules_Router);
        // 2.Get the default result of the route judgment when the engine executes ture or false (true means the route can be passed, false means it can't be passed).
        boolean isPass = (Boolean) getParameter(StaticVarExtend.Para_RouterRules_IsPass);
        // 3.Self-processing judgment content

        // 4.Returns whether this route is allowed to pass through the
        // true Allowed to pass flase Not allowed to pass
        return true;
    }
}


