package cc.smtweb.system.bpm.web.engine.flow;

import cc.smtweb.framework.core.db.DbEngine;
import cc.smtweb.framework.core.db.EntityHelper;
import cc.smtweb.framework.core.exception.BizException;
import cc.smtweb.system.bpm.web.design.flow.FlowConst;
import cc.smtweb.system.bpm.web.design.flow.ModelProcHelper;
import cc.smtweb.system.bpm.web.design.flow.define.Activity;
import cc.smtweb.system.bpm.web.design.flow.define.ProcInfo;
import cc.smtweb.system.bpm.web.design.flow.define.Trans;
import cc.smtweb.system.bpm.web.design.form.ModelForm;
import cc.smtweb.system.bpm.web.design.form.ModelFormHelper;
import cc.smtweb.system.bpm.web.engine.flow.entity.Candidate;
import cc.smtweb.system.bpm.web.engine.flow.entity.Task;
import cc.smtweb.system.bpm.web.engine.flow.entity.TaskRel;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Akmm at 13-6-24 下午9:42
 * 单据
 */
public class FlowHelper {
    //页面定义中流程数据集名
    public final static String DATASET_NAME_FLOW = "flow";
    //页面定义中流程审批数据集名
    public final static String DATASET_NAME_COMMENT = "comment";

    //获取页面单据类型
    public static long getBillType(String pageId) {
        ModelForm form = ModelFormHelper.getFromCache(pageId);
        long billType = form.getBillType();
        if (billType <= 0L) throw new BizException("此页面非单据页面，不能使用流程服务！");
        return billType;
    }

    //是否我的待办任务
    public static boolean isMyWaitedTask(long task_id, long user_id) {
        return DbEngine.getInstance().isExists("select 1 from " + EntityHelper.getSchemaTableName(Candidate.ENTITY_NAME) +
                " where cnd_tsk_id=? and cnd_user_id=?", task_id, user_id);
    }

    public static boolean isMySubmitTask(long task_id, long user_id) {
        return DbEngine.getInstance().isExists("select 1 from " + EntityHelper.getSchemaTableName(TaskRel.ENTITY_NAME) +
                " r inner join " + EntityHelper.getSchemaTableName(Task.ENTITY_NAME) + " t on t.tsk_id = r.trl_src_task_id\n" +
                " where r.trl_dst_task_id=? and t.tsk_handler=?", task_id, user_id);
    }

    public static void stopTask(long billId, long tskId) {
        DbEngine.getInstance().update("update " + EntityHelper.getSchemaTableName(Task.ENTITY_NAME) +
                " set tsk_statu=? where tsk_pri_id=? and tsk_id<>? and tsk_statu<?", FlowConst.ActivityStatu.STOP.value, billId, tskId, FlowConst.ActivityStatu.SUBMIT.value);
    }

    /**
     * 得到指定活动的下一任务节点
     *
     * @param act_id
     * @return
     */
    public static List<Activity> getNextActivity(FlowInstance flowInstance) {
        Activity act = ModelProcHelper.getNextActivity(flowInstance.getActInst().getPrcId(), flowInstance.getActInst().getActId());
        if (act == null) {
            throw new BizException("未找到可用的活动节点定义！");
        }
        List<Activity> listRet = new ArrayList<>();
        buildNextActivityRes(act, flowInstance, listRet);
        if (listRet.isEmpty()) {
            throw new BizException("未找到可用的活动节点定义！");
        }
        return listRet;
    }

    /**
     * 递归处理，兼容判断后面加判断，并发后面跟并发
     *
     * @param act
     * @param flowInstance
     * @param listRet
     * @throws Exception
     */
    private static void buildNextActivityRes(Activity act, FlowInstance flowInstance, List<Activity> listRet) {
        //待返回的结果集
//        if (act.getActType() == FlowConst.ActivityType.scriptTask) 自动任务暂不支持
        ProcInfo proc = flowInstance.getProcDef().getProcInfo();
        if (act.getType() == FlowConst.ActivityType.CONDITION.value) {//条件分支
            List<Trans> list = ModelProcHelper.getNextTrans(flowInstance.getProcInst().getPrcId(), act.getId());
            for (Trans t : list) {
                if (flowInstance.execTrans(t.getFilter())) {
                    Activity a = proc.findActivity(t.getDst());
                    if (a == null) {
                        throw new BizException("无效的活动节点定义（" + t.getDst() + "）！");
                    }
                    buildNextActivityRes(a, flowInstance, listRet);
                    break;
                }
            }
        } else if (act.getType() == FlowConst.ActivityType.PARALLEL.value) {//并发分支
            List<Trans> list = ModelProcHelper.getNextTrans(flowInstance.getProcDef().getId(), act.getId());
            for (Trans t : list) {
                if (flowInstance.execTrans(t.getFilter())) {
                    Activity a = proc.findActivity(t.getDst());
                    if (a == null) {
                        throw new BizException("无效的活动节点定义（" + t.getDst() + "）！");
                    }
                    buildNextActivityRes(a, flowInstance, listRet);
                }
            }
        } else {
            listRet.add(act);
        }
    }

}
