package com.persagy.adm.diagram.controller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.persagy.adm.diagram.core.ContentParser;
import com.persagy.adm.diagram.core.DataStrategy;
import com.persagy.adm.diagram.core.model.Diagram;
import com.persagy.adm.diagram.core.model.DiagramNode;
import com.persagy.adm.diagram.core.model.EquipmentNode;
import com.persagy.adm.diagram.core.model.Line;
import com.persagy.adm.diagram.core.model.base.Container;
import com.persagy.adm.diagram.core.model.base.IComponent;
import com.persagy.adm.diagram.core.model.template.DiagramTemplate;
import com.persagy.adm.diagram.frame.BdtpRequest;
import com.persagy.adm.diagram.manage.DemoDiagramManager;
import com.persagy.dmp.common.constant.ResponseCode;
import com.persagy.dmp.common.exception.BusinessException;
import com.persagy.dmp.common.model.response.CommonResult;
import com.persagy.dmp.common.utils.ResultHelper;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * 系统图相关接口
 *
 * @author liyang
 * @date 2022-01-04
 */
@RestController
@CrossOrigin
@RequestMapping("/diagram")
public class DiagramController {

    @Autowired
    @Qualifier("dataStrategyImpl")
    private DataStrategy dataStrategy;
    @Autowired
    private DemoDiagramManager diagramManager;
    @Autowired
    private ContentParser parser;

    /**
     * 系统图列表接口
     *
     * @param diagram 请求参数
     * @return 系统图列表
     */
    @ApiOperation("系统图列表接口")
    @PostMapping("/getDiagrams")
    public CommonResult<List<Diagram>> getDiagrams(@RequestBody Map<String, Object> diagram) {
        BdtpRequest current = BdtpRequest.getCurrent();
        String groupCode = current.getGroupCode();
        String projectId = current.getProjectId();

        List<Diagram> diagramList = dataStrategy.getDiagrams(null, projectId,
                (String) diagram.get("systemId"), groupCode, (String) diagram.get("name"), (Boolean) diagram.get("flag"));

        return ResultHelper.multi(diagramList);
    }

    /**
     * 新增或修改系统图
     *
     * @param params    参数集合
     * @param projectId 项目id
     * @param groupCode 集团code
     * @return 系统图信息
     */
    @ApiOperation("新增系统图")
    @PostMapping("/newDiagram")
    public CommonResult<Diagram> newDiagram(@RequestBody Map<String, Object> params,
                                            @RequestParam String projectId,
                                            @RequestParam String groupCode) {
        Diagram diagram = new Diagram();
        diagram.setGroupCode(groupCode);
        diagram.setProjectId(projectId);

        Optional.ofNullable(params).ifPresent(map -> {
            Optional.ofNullable(map.get("id")).ifPresent(o -> diagram.setId(String.valueOf(o)));
            Optional.ofNullable(map.get("type")).ifPresent(o -> {
                if (String.valueOf(o).length() < 4) {
                    throw new BusinessException(ResponseCode.A0400.getCode(), "type参数非法");
                }
                diagram.setType(String.valueOf(o));
                diagram.setSystem(String.valueOf(o).substring(0, 4));
            });
            Optional.ofNullable(map.get("systemId")).ifPresent(o -> diagram.setSystemId(String.valueOf(o)));
            Optional.ofNullable(map.get("name")).ifPresent(o -> diagram.setName(String.valueOf(o)));
            Optional.ofNullable(map.get("remark")).ifPresent(o -> diagram.setRemark(String.valueOf(o)));
            Optional.ofNullable(map.get("templateId")).ifPresent(o -> diagram.setTemplateId(String.valueOf(o)));
            Optional.ofNullable(map.get("extraProps")).ifPresent(s -> {
                Map<String, Object> m = parser.parseContent(parser.toJson(s), Map.class);
                diagram.setExtraProp("state", m.get("state"));
            });
            buildLinesAndNodes(diagram, map);
        });

        return ResultHelper.single(dataStrategy.saveDiagram(diagram));
    }

    /**
     * 构建lines modes 数据
     *
     * @param diagram 系统图对象
     * @param map     输入参数集合
     */
    private void buildLinesAndNodes(Diagram diagram, Map<String, Object> map) {
        Optional.ofNullable(map.get("lines")).ifPresent(lines ->
                diagram.setLines(Arrays.asList(parser.parseContent(parser.toJson(lines), Line[].class))));
        List<DiagramNode> nodes = new ArrayList<>();
        Optional.ofNullable(map.get("template")).flatMap(template ->
                Optional.ofNullable(parser.parseContent(parser.toJson(template), DiagramTemplate.class)))
                .ifPresent(diagramTemplate -> {
                    List<Container> containers = diagramTemplate.getContainers();
                    if (CollectionUtil.isNotEmpty(containers)) {
                        containers.forEach(container -> {
                            if (container.isEquipmentBox()) {
                                List<IComponent> children = container.getChildren();
                                if (CollectionUtil.isNotEmpty(children)) {
                                    children.forEach(iComponent -> {
                                        if (StrUtil.equalsIgnoreCase(iComponent.getCompType(), EquipmentNode.TYPE)) {
                                            DiagramNode node = parser.parseContent(parser.toJson(iComponent), DiagramNode.class);
                                            nodes.add(node);
                                        }
                                    });
                                }
                            }
                        });
                    }
                });
        diagram.setNodes(nodes);
    }

    /**
     * 系统图删除功能
     *
     * @param diagramId 系统图id
     * @return 是否成功
     */
    @ApiOperation("删除系统图")
    @GetMapping("/deleteDiagram")
    public CommonResult<Boolean> deleteDiagram(String diagramId) {
        return ResultHelper.single(dataStrategy.deleteDiagram(diagramId));
    }

    /**
     * 根据系统图id获取系统图信息
     *
     * @param diagramId 系统图id
     * @return 系统图对象信息
     */
    @ApiOperation("根据系统图id获取系统图信息")
    @GetMapping("/getDiagram")
    public CommonResult<Diagram> getDiagram(String diagramId) {
        Diagram diagram = dataStrategy.getDiagram(diagramId);
        diagramManager.buildDiagram(diagram, true);
        return ResultHelper.single(diagram);
    }

    /**
     * 系统实例查询
     *
     * @return 系统实例
     */
    @ApiOperation("系统实例查询")
    @PostMapping("/system/instance")
    public CommonResult<List<ObjectNode>> loadSystemInstance() {
        BdtpRequest current = BdtpRequest.getCurrent();
        String groupCode = current.getGroupCode();
        String projectId = current.getProjectId();
        return ResultHelper.multi(dataStrategy.loadSystemInstance(projectId, groupCode));
    }

    /**
     * 项目下的专业 -> 系统 ->系统实例 的树状结构数据
     *
     * @return 列表
     */
    @ApiOperation("项目下的专业 -> 系统 ->系统实例 的树状结构数据")
    @PostMapping("/major/system/instance")
    public CommonResult<List<ObjectNode>> loadMajorSystemInstance() {
        return ResultHelper.multi(dataStrategy.loadMajorSystemInstance());
    }

    /**
     * 根据系统类获取系统类型下的模板列表  以树状结构数据返回
     *
     * @param diagram diagram.getSystem() 参数
     * @return 列表
     */
    @ApiOperation("据系统类获取系统类型下的模板列表")
    @PostMapping("/systemType/template")
    public CommonResult<List<ObjectNode>> loadSystemTypeTemplate(@RequestBody Diagram diagram) {
        return ResultHelper.multi(dataStrategy.loadSystemTypeTemplate(diagram));
    }

    /**
     * 根据系统图类型获取模板列表
     *
     * @param diagramType 系统图类型
     * @return 模板列表
     */
    @ApiOperation("根据系统图类型获取模板列表")
    @GetMapping("/getTemplates/ByType")
    public CommonResult<List<DiagramTemplate>> getTemplatesByType(String diagramType) {
        return ResultHelper.multi(dataStrategy.getTemplates(diagramType));
    }

    /**
     * 根据模板id获取系统模板信息
     *
     * @param templateId 模板id
     * @return 模板信息
     */
    @ApiOperation("根据模板id获取系统模板信息")
    @GetMapping("/getTemplate/ById")
    public CommonResult<DiagramTemplate> getTemplateById(String templateId) {
        return ResultHelper.single(dataStrategy.getTemplate(templateId));
    }

    /**
     * 获取所有的系统模板
     *
     * @return 模板列表
     */
    @ApiOperation("获取所有的系统模板")
    @GetMapping("/getTemplates")
    public CommonResult<List<DiagramTemplate>> getTemplates() {
        return ResultHelper.multi(dataStrategy.getTemplates());
    }

    /**
     * 加载数据
     *
     * @return 模板列表
     */
    @ApiOperation("加载数据")
    @PostMapping("/loadData")
    public CommonResult<Diagram> loadData(@RequestBody Diagram diagram) {
        return ResultHelper.single(diagramManager.loadData(diagram.getId(), true));
    }

    /**
     * 系统图状态变更
     *
     * @return 是否成功
     */
    @ApiOperation("系统图状态变更")
    @PostMapping("/update/state")
    public CommonResult<Boolean> updateState(@RequestBody Map<String, String> params) {
        return ResultHelper.single(dataStrategy.updateState(params.get("state"), params.get("id")));
    }

    /**
     * 查看系统实例是否有发布状态的系统图
     *
     * @return 是否成功
     */
    @ApiOperation("查看系统实例是否有发布状态的系统图")
    @PostMapping("/system/instance/diagram/list")
    public CommonResult<Map<String, Boolean>> querySystemInstanceDiagramList() {
        return ResultHelper.single(dataStrategy.querySystemInstanceDiagramList());
    }
}
