/**
 * Copyright &copy; 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
 */
package com.jeeplus.modules.flowable.web;

import com.google.common.collect.Lists;
import com.jeeplus.common.json.AjaxJson;
import com.jeeplus.common.utils.StringUtils;
import com.jeeplus.core.web.BaseController;
import com.jeeplus.modules.flowable.service.FlowTaskService;
import com.jeeplus.modules.sys.utils.UserUtils;
import net.sf.json.JSONObject;
import net.sf.json.JSONString;
import org.flowable.bpmn.model.BaseElement;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.bpmn.model.StartEvent;
import org.flowable.bpmn.model.UserTask;
import org.flowable.engine.*;
import org.flowable.engine.form.FormProperty;
import org.flowable.engine.form.StartFormData;
import org.flowable.engine.form.TaskFormData;
import org.flowable.variable.api.history.HistoricVariableInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

/**
 * 流程个人任务相关Controller
 *
 * @author jeeplus
 * @version 2016-11-03
 */
@RestController
@RequestMapping("/flowable/form")
public class FlowableFormController extends BaseController {

    @Autowired
    private FlowTaskService flowTaskService;

    @Autowired
    private FormService formService;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private HistoryService historyService;

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private TaskService taskService;

    @Autowired
    private IdentityService identityService;


    /**
     * 提交表单
     *
     * @param processDefinitionId 流程定义ID
     */
    @PostMapping("submitStartFormData")
    public AjaxJson submitStartFormData(String processDefinitionId,@RequestParam("title") String title, @RequestParam("data") String data) {
        StartFormData formData = formService.getStartFormData(processDefinitionId);//拿取流程启动前的表单字段。
        List<FormProperty> formProperties = formData.getFormProperties();//获取表单字段值
        JSONObject jData = JSONObject.fromObject(data);

        // 设置流程变量
        Map<String,String> formValues = new HashMap<String,String>();
        String userId = UserUtils.getUser().getId();
        String userName = UserUtils.get(userId).getName();
        formValues.put("userName", userName);

        // 用来设置启动流程的人员ID，引擎会自动把用户ID保存到activiti:initiator中
        identityService.setAuthenticatedUserId(userId);

        // 设置流程标题
        if (StringUtils.isNotBlank(title)) {
            formValues.put("title", title);
        }

        for(FormProperty formProperty:formProperties){
            if (formProperty.isWritable()) {
                if(jData.has(formProperty.getId())){
                    String value = jData.getString(formProperty.getId());//拿取具体参数值
                    formValues.put(formProperty.getId(), value);
                }
            }

        }

        String procInsId = formService.submitStartFormData(processDefinitionId,formValues).getId();//启动流程，提交表单
        return AjaxJson.success("启动成功").put("procInsId", procInsId);
    }

    /**
     * 获取表单数据
     *
     * @param taskId 任务ID
     */
    @GetMapping("getTaskFormData")
    public AjaxJson getTaskFormData(String taskId) {

        TaskFormData taskFormData = formService.getTaskFormData(taskId);//根据任务ID拿取表单数据
        return AjaxJson.success().put("taskFormData", taskFormData.getFormProperties());
    }

    /**
     * 获取表单启动弄数据
     *
     * @param processDefinitionId 流程定义id
     */
    @GetMapping("getStartFormData")
    public AjaxJson getStartFormData(String processDefinitionId) {

        StartFormData startFormData = formService.getStartFormData(processDefinitionId);//根据流程定义ID拿取表单数据
        return AjaxJson.success().put("startFormData", startFormData.getFormProperties());
    }

    /**
     * 获取历史表单数据
     *
     * @param processIntanceId 流程实例Id
     */
    @GetMapping("getHistoryTaskFormData")
    public AjaxJson getHistroyTaskFormData(String processIntanceId, String procDefId, String taskDefKey) {
        List<HistoricVariableInstance> historicVariableInstances=historyService.createHistoricVariableInstanceQuery().processInstanceId(processIntanceId)
                .list();
//flowTaskService.getNodeBaseElement()
//        List<HistoricDetail> formProperties = historyService.createHistoricDetailQuery().executionId(taskId).formProperties().list();
        List<Map> list = Lists.newArrayList();
//        for(HistoricDetail historicDetail: formProperties){
//            Map map = new HashMap();
//            HistoricFormProperty historicFormProperty = (HistoricFormProperty)historicDetail;
//            map.put("id", historicFormProperty.getPropertyId());
//            map.put("value", historicFormProperty.getPropertyValue());
//            map.put("readable", true);
//            map.put("writable", false);
//            list.add(map);
//        }
        FlowElement node = repositoryService.getBpmnModel(procDefId).getFlowElement(taskDefKey);
        List<org.flowable.bpmn.model.FormProperty> formPropertyList = Lists.newArrayList();
        if(node!=null){
            if(node instanceof UserTask){
                formPropertyList = ((UserTask) node).getFormProperties();
            }else if(node instanceof StartEvent){
                formPropertyList = ((StartEvent) node).getFormProperties();
            }
        }
        HashMap<String,Boolean> formPropertyMap = new HashMap<>();
        for(org.flowable.bpmn.model.FormProperty formProperty : formPropertyList){
            try {
                Field field =  formProperty.getClass().getDeclaredField("readable");
                field.setAccessible(true);
                boolean readable =(boolean) field.get(formProperty);
                formPropertyMap.put(formProperty.getId(), readable);
            }catch (Exception e){

            }

        }
        for(HistoricVariableInstance historicVariableInstance: historicVariableInstances){
            Map map = new HashMap();
            boolean readable = false;
            if(formPropertyMap.get(historicVariableInstance.getVariableName()) == null || formPropertyMap.get(historicVariableInstance.getVariableName()) == true){
                readable = true;
            }
            map.put("id", historicVariableInstance.getVariableName());
            map.put("value", historicVariableInstance.getValue());
            map.put("readable", readable);
            map.put("writable", false);
            list.add(map);
        }
        return AjaxJson.success().put("taskFormData", list);
    }

    /**
     * 提交表单
     *
     * @param taskId 任务ID
     */
    @PostMapping("submitTaskFormData")
    public AjaxJson submitTaskFormData(String taskId, @RequestParam("data") String data) {
        TaskFormData taskFormData = formService.getTaskFormData(taskId);//根据任务ID拿取表单数据
        List<FormProperty> formProperties = taskFormData.getFormProperties();//获取表单字段值
        JSONObject jData = JSONObject.fromObject(data);
        Map<String, String> formValues = new HashMap<String, String>();
        HashSet noCommitValues = new HashSet();

        for (FormProperty formProperty : formProperties) {
            if (!formProperty.isWritable()) {
               noCommitValues.add(formProperty.getId());
            }
        }

        for(Object str: jData.keySet()){

          if(!noCommitValues.contains(str.toString())){
              Object o = jData.get(str.toString());
              String value = jData.getString(str.toString());//拿取具体参数值
              formValues.put(str.toString(), value);    //将ID和value存入map中
          }

        }
        formService.submitTaskFormData(taskId, formValues);    //提交用户任务表单并且完成任务。
        return AjaxJson.success("提交成功");
    }


}
