package com.huigou.bpm.management.controller;

import com.huigou.bpm.management.GraphUtils;
import com.huigou.bpm.management.application.ProcessDefinitionApplication;
import com.huigou.bpm.management.domain.model.ProcessDefinition;
import com.huigou.bpm.management.domain.model.ServiceMapping;
import com.huigou.bpm.management.domain.model.ServiceParamMapping;
import com.huigou.bpm.management.domain.query.ProcessDefinitionQueryRequest;
import com.huigou.domain.ValidStatus;
import com.huigou.uasp.annotation.ControllerMapping;
import com.huigou.uasp.client.CommonController;
import com.huigou.util.SDO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.Assert;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;

/**
 * 流程定义管理
 *
 * @author yonghuan
 */
@ControllerMapping("/bpm/procdef")
@Controller
public class ProcessDefinitionController extends CommonController {

    @Autowired
    private ProcessDefinitionApplication processDefinitionApplication;

    /**
     * 跳转到流程定义列表页面.
     */
    public String forwardProcdef() {
        return forward("procdefList");
    }

    /**
     * 查询流程定义分类
     */
    public String queryProcdefKind() {
        return toResult(processDefinitionApplication.queryProcessDefinitionKind(getSDO().getParentId()));
    }

    /**
     * 新增流程定义分类
     */
    public String addProcdefKind() {
        ProcessDefinition definitionKind = getSDO().toObject(ProcessDefinition.class);
        definitionKind.setNodeKindId(0);
        return success(processDefinitionApplication.add(definitionKind));
    }

    /**
     * 删除流程定义分类
     */
    public String deleteProcdefKind() {
        processDefinitionApplication.deleteProcessDefinitionKind(getSDO().getId());
        return success();
    }

    /**
     * 修改流程定义分类
     */
    public String updateProcdefKind() {
        ProcessDefinition definitionKind = getSDO().toObject(ProcessDefinition.class);
        return success(processDefinitionApplication.updateProcessDefinitionKind(definitionKind));
    }

    /**
     * 加载流程定义分类详情页
     */
    public String loadProcdefKind() {
        ProcessDefinition definitionKind = processDefinitionApplication.queryProcessDefinitionKindById(getSDO().getId());
        Assert.notNull(definitionKind, "分类不存在");
        return forward("/common/CommonTreeDetail.jsp", definitionKind);
    }

    /**
     * 修改排序号
     */
    public String updateSequence() {
        Map<String, Integer> params = this.getSDO().getStringMap("data");
        processDefinitionApplication.updateSequence(params);
        return success();
    }

    /**
     * 查询流程定义。
     */
    public String sliceQueryProcessDefinitions() {
        return toResult(processDefinitionApplication.sliceQueryProcessDefinition(getSDO().toQueryRequest(ProcessDefinitionQueryRequest.class)));
    }

    /**
     * 跳转到添加流程定义的界面。
     */
    public String showAddProcessDefinition() {
        return forward("procdefDetails");
    }

    public String addProcessDefinition() {
        ProcessDefinition definition = getSDO().toObject(ProcessDefinition.class);
        definition.setNodeKindId(1);
        processDefinitionApplication.add(definition);
        return success();
    }

    /**
     * 跳转到修改流程定义界面。
     */
    public String showProcessDefinition() {
        ProcessDefinition definition = processDefinitionApplication.queryById(getSDO().getId());
        Assert.notNull(definition, "流程定义不存在");
        return forward("procdefDetails", definition);
    }

    public String updateProcessDefinition() {
        processDefinitionApplication.updateProcessDefinitionById(getSDO().toObject(ProcessDefinition.class));
        return success();
    }

    /**
     * 启用流程定义。
     */
    public String enableProcessDefinition() {
        processDefinitionApplication.updateStatus(getSDO().getIds(), ValidStatus.ENABLED.id);
        return success();
    }

    /**
     * 禁用流程定义。
     */
    public String disableProcessDefinition() {
        processDefinitionApplication.updateStatus(getSDO().getIds(), ValidStatus.DISABLED.id);
        return success();
    }

    /**
     * 删除流程定义。
     */
    public String deleteProcessDefinition() {
        processDefinitionApplication.deleteProcessDefinition(getSDO().getIds());
        return success();
    }

    /**
     * 移动流程定义。
     */
    public String moveProcessDefinition() {
        SDO params = getSDO();
        List<String> ids = params.getStringList("ids");
        String parentId = params.getString("parentId");
        processDefinitionApplication.moveProcessDefinition(ids, parentId);
        return success();
    }

    /**
     * 为流程活动绑定业务服务。
     */
    public String bindService(SDO sdo) {
        ServiceMapping mapping = sdo.toObject(ServiceMapping.class);
        List<ServiceParamMapping> paramMappings = sdo.getList("paramMappings", ServiceParamMapping.class);
        processDefinitionApplication.bindService(mapping, paramMappings);
        return success();
    }

    public String clearService(SDO sdo) {
        ServiceMapping mapping = sdo.toObject(ServiceMapping.class);
        processDefinitionApplication.clearService(mapping.getProcdefId(), mapping.getActivityCode());
        return success();
    }

    public String queryServiceByActivityCode(SDO sdo) {
        ServiceMapping mapping = sdo.toObject(ServiceMapping.class);
        return toResult(processDefinitionApplication.queryServiceByActivityCode(mapping.getProcdefId(), mapping.getActivityCode()));
    }

    /**
     * 导出流程图图片。
     */
    public String exportImage(SDO sdo, HttpServletRequest request, HttpServletResponse response) throws Exception {
        ProcessDefinition pd = processDefinitionApplication.queryById(sdo.getId());
        String fileName = encodeAttachmentName(request, pd.getName() + ".png");
        response.setContentType("image/png");
        response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\";");
        try (OutputStream os = response.getOutputStream()) {
            GraphUtils.writeImage("png", pd.getImageWidth(), pd.getImageHeight(), null, pd.getImageXml(), os);
        }
        return NONE;
    }

    @Override
    protected String getPagePath() {
        return "/system/tbpm/procdef/";
    }
}
