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;

/**
 * 接口实现类的说明示例
 * 必须继承已有的类 com.horizon.wf.core.rule.BaseRuleImpl
 */
public class Example extends BaseRuleImpl implements IBaseRule {

    /**
     * 具体的实现,参考下面方法中的说明,所有的实现都差不多结构,
     * 只有自定义的异常处理接口实现中是没有传入 runningdata的.
     * 不同的接口 仅仅是额外传入的参数有些差异,额外的参数多数都是可以从runningdata中获取的
     * 系统为了方便接口的实现,额外传入了一些认为会用到的参数
     * @return
     */
    @Override
    public boolean executeRule() {

        return false;
    }

    /**
     * 内部循环节点
     * 如果前台没有传入办理人,则判断是否有接口类
     * @return
     */
    private boolean doProgressively(){
        // 从引擎获取到核心数据对象(如果接口没有额外传入需要的数据时,可以从此对象中获取)
        RunningData runningdata = getRunningdata();
        DBWork work = (DBWork)getParameter(StaticVarExtend.Parameter_DBWork);// runningdata.getWork());
        WorkParaBean paraBean =(WorkParaBean)getParameter(StaticVarExtend.Parameter_WorkParaBean);// 设置前后台对象到接口
        IFlowNode curNode = (IFlowNode)getParameter(StaticVarExtend.Parameter_Current_IFlowNode);// 逐级审批节点
        IRunUser user = (IRunUser) getParameter(StaticVarExtend.Parameter_RunUser);// 当前操作者
        String userid = (String)getParameter(StaticVarExtend.Parameter_Progressive_Userid);// 提交到逐级审批节点的人员id

        // 通过setResult("")方法把下一个办理人的id返回给引擎

        // 返回ture,引擎从返回结果中获取办理人,false则忽略
        return true;
    }

    /**
     * 合并网关 合并处理
     * @return
     */
    private boolean doGatewayMerger(){
        // 从引擎获取到核心数据对象(如果接口没有额外传入需要的数据时,可以从此对象中获取)
        RunningData runningdata = getRunningdata();

        WorkParaBean paraBean = (WorkParaBean)getParameter(StaticVarExtend.Parameter_WorkParaBean);
        IFlowNode curNode = (IFlowNode)getParameter(StaticVarExtend.Parameter_GateWay_IFlowNode);// 当前节点
        // 所有需要到达合并网关的分支列表
        List<ITrackJson> lstTrack = (List<ITrackJson>) getParameter(StaticVarExtend.Parameter_GateWay_Alltracks);// 设置所有分支路径信息到接口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());

        // 如果有需要撤销的分支,请使用setResult("")方法把需要撤销的分支路径id返回给引擎

        // 返回是否允许离开 true 允许离开 false 不允许离开
        return true;
    }

    /**
     * 多人并行节点离开规则中的自定义
     * 调用入口 com.horizon.wf.expand.node.NodeMultiImpl#doNormal
     * @return
     */
    private boolean doNodeMultilLeave(){
        // 从引擎获取到核心数据对象(如果接口没有额外传入需要的数据时,可以从此对象中获取)
        RunningData runningdata = getRunningdata();

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

        // 返回是否允许离开 true 允许离开 false 不允许离开
        return true;
    }

    /**
     * 合并节点激活方式中的定义实现
     *
     * @return
     */
    private boolean doMergerEntryType(){
        // 从引擎获取到核心数据对象(如果接口没有额外传入需要的数据时,可以从此对象中获取)
        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);// 进入的节点

        int allTrackNum = (Integer)getParameter("AllTrackNum"); // 所有需要到达的分支数
        int reachedNum = (Integer)getParameter("ReachedTrackNum"); // 已经到达的分支数


        // 返回是否允许离开 true 允许离开 false 不允许离开
        return true;
    }
    /**
     * 合并节点的离开方式中的自定义实现
     * 调用入口 com.horizon.wf.expand.node.NodeMergerImpl#checkMergerNodeLeaveRule
     * @return
     */
    private boolean doMergerLeaveType(){
        // 从引擎获取到核心数据对象(如果接口没有额外传入需要的数据时,可以从此对象中获取)
        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);


        // 返回是否允许离开 true 允许离开 false 不允许离开
        return true;
    }


    /**
     * 异常处理接口实现示范代码
     * 调用入口 com.horizon.wf.action.common.ActionCommon#dealException
     * @return
     */
    private boolean doException(){
        // 1.引擎调用时,传入的参数对象
        WorkParaBean paraBean = (WorkParaBean) getParameter(StaticVarExtend.Parameter_WorkParaBean);
        // 2.当前实例对象
        DBWork work = (DBWork) getParameter(StaticVarExtend.Parameter_DBWork);
        // 3.当前路径对象
        DBTrack track = (DBTrack) getParameter(StaticVarExtend.Parameter_DBTrack);
        // 4.当前异常定义对象
        INodeException e = (INodeException) getParameter(StaticVarExtend.Parameter_Exception_INodeException);

        // 5.异常处理内容

        // 返回true,异常执行结束,
        // 如果返回 false,可以使用setResult指定一个系统默认处理的方式: setResult("2"); 也可以不设置跟返回true一样
        // 2 = 跳转 ,3= 挂起,4=终止,其他值系统忽略处理
        return true;
    }

    /**
     * 节点进入的扩展实现示例代码(只有在其少数情况下才会用到)
     * 调用入口 com.horizon.wf.rule.defa.core.EntryRuleDefault#actionInterface
     * @return
     */
    private boolean doNodeEntry(){
        // 从引擎获取到核心数据对象(如果接口没有额外传入需要的数据时,可以从此对象中获取)
        RunningData runningdata = getRunningdata();
        // 要进入的节点对象
        IFlowNode entryNode = (IFlowNode) getParameter(StaticVar.Para_EntryRules_IXmlNode);
        // 指向要进入的节点的路由
        INodeRouter fromRouter =(INodeRouter) getParameter(StaticVar.Para_EntryRules_IXmlRouter);
        // 节点进入的方式,1按路由方向进入,2=退回的方式进入,3=跳转的方式进入
        int leaveType = (Integer)getParameter(StaticVar.Para_EntryRules_LeaveType);
        // 退回时使用的参数,一般是要退回的节点原来所在的路径id
        String oldTrackid =(String)getParameter(StaticVar.Para_EntryRules_OldTrackidForReject);

        //需要执行的代码

        // 返回true 表示节点允许进入,false表示不允许进入
        return true;
    }
    /**
     * 节点离开的扩展实现示例代码(只有在其少数情况下才会用到)
     * 调用入口 com.horizon.wf.rule.defa.core.LeaveRuleDefault
     * @return
     */
    private boolean doNodeLeave(){
        // 从引擎获取到核心数据对象(如果接口没有额外传入需要的数据时,可以从此对象中获取)
        RunningData runningdata = getRunningdata();
        // 当前节点对象(离开只有当前节点才会有)
        IFlowNode curNode = (IFlowNode) getParameter(StaticVar.Para_LeaveRules_IXmlNode);

        // 需要执行的代码
        // 比如要实现在节点离开时想要对节点参数进行修改的功能如下:
        List<INodePara> paraList = runningdata.getCurFlowNode().getAllNodePara();
        INodePara para = paraList.get(0);

        String initValue = para.getInitialValue();
        // 获取当前节点参数的数据
        String oldValue = runningdata.getThisNodeParaValue(para.getParaId());
        int tmp = 0;
        if(CStrUtil.isNull(oldValue)){
            tmp = Integer.parseInt(initValue);
        }
        else{
            tmp = Integer.parseInt(oldValue);
        }
        tmp += 1;
        // 给当前节点参数赋值
        runningdata.setThisNodeParaValue(para.getParaId(),""+tmp);
        // -----上面的代码,仅供参考----------

        // 返回true 表示节点允许离开,false表示不允许离开
        return true;
    }

    /**
     * 节点事件处理实现类的示范代码
     * 调用入口 com.horizon.wf.rule.event.EventUtil#excuteEvents
     * @return
     */
    private boolean doNodeEvent(){
        // 从引擎获取到核心数据对象(如果接口没有额外传入需要的数据时,可以从此对象中获取)
        RunningData runningdata = getRunningdata();
        //事件处理类额外传入参数
        // 1.执行事件的节点对象
        IFlowNode eventNode = (IFlowNode) getParameter(StaticVarExtend.Parameter_IFlowNode);
        // 2.当前节点对象
        IFlowNode curNode = (IFlowNode)getParameter(StaticVarExtend.Parameter_Current_IFlowNode);
        // 3.引擎调用时,传入的参数对象
        WorkParaBean paraBean = (WorkParaBean)getParameter(StaticVarExtend.Parameter_WorkParaBean);
        // 4.当前实例对象
        DBWork work = (DBWork)getParameter(StaticVarExtend.Parameter_DBWork);
        // 5.当前执行人对象
        IRunUser user = (IRunUser) getParameter(StaticVarExtend.Parameter_RunUser);
        // 6.当前路径对象
        DBTrack track = (DBTrack)getParameter(StaticVarExtend.Parameter_DBTrack);
        // 7.需要保存的SQL数据如果需要引擎来保存,请放入此 map中(key=SQL,value=List为SQL中对应的参数)
        Map<String, List<Object>> dataMap = (Map<String, List<Object>>) getParameter(StaticVarExtend.Parameter_SaveMap);
        // 8.事件类型
        String eventType = (String)getParameter("eventType");
        // 9.事件实际执行内容

        // 10.返回 true 表示执行成功,引擎从第7步中的dataMap里获取需要保存的数据,引擎继续往下执行,
        // 返回 false表示执行失败, 引擎会根据事件类型,确定是否继续往下执行
        return true;
    }

    /**
     * 事件节点的进入扩展类
     * @return
     */
    private boolean doEventNodeEntry(){
        // 从引擎获取到核心数据对象(如果接口没有额外传入需要的数据时,可以从此对象中获取)
        RunningData runningdata = getRunningdata();

        WorkParaBean paraBean = (WorkParaBean)getParameter(StaticVarExtend.Parameter_WorkParaBean);// 设置前后台对象到接口
        DBWork work = (DBWork) getParameter(StaticVarExtend.Parameter_DBWork);
        IRunUser user = (IRunUser)getParameter(StaticVarExtend.Parameter_RunUser);
        DBTrack track = (DBTrack)getParameter(StaticVarExtend.Parameter_DBTrack);
        // 如果需要引擎保存数据,则放入savemap中,引擎会从中获取到
        Map<String, List<Object>> saveMap = (Map<String,List<Object>>)getParameter(StaticVarExtend.Parameter_SaveMap);

        // 返回true,允许事件节点进入,false 不允许
        return true;
    }

    /**
     * 自定义接口实现 获取办理人的示范代码
     * 调用入口 com.horizon.wf.rule.defa.core.EntryRuleDefault#getUserFromCustom
     * @return
     */
    private boolean doCustomUser(){
        // 从引擎获取到核心数据对象(如果接口没有额外传入需要的数据时,可以从此对象中获取)
        RunningData runningdata = getRunningdata();
        // 下面参数为获取办理人时,额外传入的对象
        // 1.引擎调用时,传入的参数对象
        WorkParaBean paraBean = (WorkParaBean)getParameter(StaticVarExtend.Parameter_WorkParaBean);
        // 2.流程定义中用来获取自定义办理人时设置的数据
        String customer = (String)getParameter(StaticVarExtend.Parameter_CustomeUser_Para);
        // 3.获取办理人的节点定义对象
        IFlowNode flowNode = (IFlowNode) getParameter(StaticVarExtend.Parameter_CustomeUser_IFlowNode);
        // 4.获取到的办理人ID
        String userId = "";
        // 5.获取的办理人返回
        setResult(userId);
        // 6.返回
        // true表示获取成功,引擎会从 第5步设置的返回值中获取结果  false,引擎忽略获取结果
        return true;
    }


    /**
     * 路由条件判断接口实现的示范代码
     * @return
     */
    private boolean doRouter(){
        // 从引擎获取到核心数据对象(如果接口没有额外传入需要的数据时,可以从此对象中获取)
        RunningData runningdata = getRunningdata();
        // 下面两个参数是此接口类被调用时,引擎额外传入的对象供以当前接口实现类使用
        // 1.获取路由定义对象 ,通过router可以获取到在流程定义中定义的数据
        INodeRouter router = (INodeRouter)getParameter(StaticVarExtend.Para_RouterRules_Router);
        // 2.获取引擎执行时路由判断时的默认结果 ture or false( true表示此路由可以通过,false表示不能通过)
        boolean isPass = (Boolean) getParameter(StaticVarExtend.Para_RouterRules_IsPass);
        // 3.自行处理判断内容

        // 4. 最终返回 此路由是否允许通过
        // true 允许通过  flase 不允许通过
        return true;
    }
}


