package com.persagy.adm.diagram.manage;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.IdUtil;
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.base.*;
import com.persagy.adm.diagram.core.model.logic.DataFilter;
import com.persagy.adm.diagram.core.model.logic.DynGroup;
import com.persagy.adm.diagram.core.model.logic.EquipPack;
import com.persagy.adm.diagram.core.model.template.DiagramTemplate;
import com.persagy.adm.diagram.core.model.template.MainPipe;
import com.persagy.adm.diagram.dao.TemplateMapper;
import com.persagy.adm.diagram.entity.DiagramType;
import com.persagy.adm.diagram.entity.TemplateEntity;
import com.persagy.adm.diagram.frame.BdtpRequest;
import com.persagy.adm.diagram.frame.EditRequest;
import com.persagy.adm.diagram.service.BdtpDataService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

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

/**
 * 模板编辑的相关操作
 *
 * @author zhaoyk
 */
@Service
public class TemplateManager {

    private final DataStrategy dataStrategy;

    @Autowired
    public TemplateManager(@Qualifier(DataStrategy.IMPL_QUALIFIER) DataStrategy dataStrategy) {
        this.dataStrategy = dataStrategy;
    }

    @Autowired
    private ContentParser contentParser;

    @Autowired
    private BdtpDataService bdtpDataService;

    /**
     * 查询系统图模板，树形结构
     */
    public List<Folder> getTemplates() {
        List<DiagramType> types = dataStrategy.getDiagramTypes();

        List<DiagramTemplate> templates = dataStrategy.getTemplates();
        for (DiagramTemplate template : templates) {
            buildTemplate(template);
        }

        BdtpRequest req = BdtpRequest.getCurrent();
//		List<ObjectNode> maj = bdtpDataService.getMajorList(req);
//		List<ObjectNode> sys = bdtpDataService.getSystemList(req);
        //TODO debug
        List<ObjectNode> maj = new ArrayList<>();
        List<ObjectNode> sys = new ArrayList<>();

        List<Folder> folders = new ArrayList<>();
        for (DiagramType type : types) {
            Folder fm = Folder.getFolder(type.getMajor(), Folder.TYPE_MAJ, folders, maj);
            Folder fs = Folder.getFolder(type.getDSystem(), Folder.TYPE_SYS, (List) fm.getChildren(), sys);

            Folder ft = new Folder();
            fs.getChildren().add(ft);
            ft.setName(type.getName());
            ft.setId(type.getCode());
            ft.setType(Folder.TYPE_TYPE);

            for (DiagramTemplate template : templates) {
                if (template.getDiagramType().equals(type.getCode())) {
					ft.getChildren().add(template);
				}
            }
        }

        return folders;
    }

    /**
     * 查询某个系统图类型下的模板列表
     */
    public List<DiagramTemplate> getTemplates(String diagramType) {
        return dataStrategy.getTemplates(diagramType);
    }

    /**
     * 创建新的模板
     */
    public DiagramTemplate createTemplate(String name, String type) {
        DiagramTemplate template = DiagramTemplate.defaultTemplate();

        template.setName(name);
        template.setDiagramType(type);
        template.setId(IdUtil.simpleUUID());

        template.setMainPipes(new ArrayList<>());

        return saveTemplate(template);
    }

    /**
     * 删除模板
     */
    public boolean deleteTemplate(String id) {
        return dataStrategy.deleteTemplate(id);
    }

    @Autowired
    private TemplateMapper templateMapper;

    /**
     * 编辑模板的基本信息
     */
    public boolean editTemplateInfo(String id, Map<String, String> infos) {
        TemplateEntity entity = templateMapper.selectById(id);
        if (entity != null) {
            if (infos.containsKey("name")) {
				entity.setName(infos.get("name"));
			}
            if (infos.containsKey("code")) {
				entity.setCode(infos.get("code"));
			}
            if (infos.containsKey("remark")) {
				entity.setRemark(infos.get("remark"));
			}
            templateMapper.updateById(entity);
            return true;
        }
        return false;
    }

    /**
     * 保存模板
     */
    public DiagramTemplate saveTemplate(DiagramTemplate template) {
        template.clearLayout(); //保存模板之前，清除布局数据
        DiagramTemplate rtn = dataStrategy.saveTemplate(template);
        buildTemplate(rtn);
        return rtn;
    }

    private void buildTemplate(DiagramTemplate template) {
        template.init();
        template.layout(new XY(0, 0));
    }

    /**
     * 添加容器
     */
    public DiagramTemplate addCon(String newContainerId, String containerId, String templateId) {
        DiagramTemplate template = dataStrategy.getTemplate(templateId);

        Container newCon = new Container();
        newCon.setId(newContainerId);
        newCon.setLayout(Layout.defaultLayout(Layout.ROW));

        Container parent = template.getContainerById(containerId);
        parent.addComp(newCon);

        return saveTemplate(template);
    }

    /**
     * 删除容器
     */
    public DiagramTemplate delCon(String containerId, String templateId) {
        DiagramTemplate template = dataStrategy.getTemplate(templateId);
        template.init();

        Container con = template.getContainerById(containerId);
        if (con.isAbsolutePosition()) {
			template.getScatteredContainers().remove(con);
		} else if (con.getParent() != null) {
			con.getParent().removeComp(containerId);
		}

        return saveTemplate(template);
    }

    /**
     * 移动容器
     */
    public DiagramTemplate moveCon(String containerId, String templateId, int offset) {
        DiagramTemplate template = dataStrategy.getTemplate(templateId);
        template.init();

        Container con = template.getContainerById(containerId);
        IContainer parent = con.getParent();
        if (parent != null) {
            List<IComponent> list = parent.getChildren();

            int idx = list.indexOf(con);
            idx += offset;

            if (idx >= 0 && idx < list.size()) {
                list.remove(con);
                list.add(idx, con);

                return saveTemplate(template);
            }
        }

        return null;
    }

    /**
     * 修改容器
     */
    public DiagramTemplate modifyCon(EditRequest.TemplatePropsData propsData, String containerId, String templateId) {
        DiagramTemplate template = dataStrategy.getTemplate(templateId);
        template.init();

        Container con = template.getContainerById(containerId);

        con.setId(propsData.getId());
        con.setName(propsData.getName());
        con.setRemark(propsData.getRemark());

        con.getLayout().setLayout(propsData.getLayout());
        con.getLayout().setMarginHeight(propsData.getMargin());
        con.getLayout().setMarginWidth(propsData.getMargin());
        con.getLayout().spaceH = con.getLayout().spaceV = propsData.getSpace();

        con.getPosition().minH = propsData.getMinH();
        con.getPosition().minW = propsData.getMinW();
        con.getPosition().setAbsolute(propsData.isAbsolute());

        con.setEquipmentTypes(CollUtil.isEmpty(propsData.getEquipTypes()) ? null : propsData.getEquipTypes());

        con.setProps(propsData.getProps());

        return saveTemplate(template);
    }

    /**
     * 绘制新的干管
     */
    public DiagramTemplate drawMainPipe(List<List<XY>> lines, String mainPipeId, String templateId) {
        lines = fixMainPipePath(lines);

        DiagramTemplate template = dataStrategy.getTemplate(templateId);
        buildTemplate(template);

        MainPipe mainPipe = null;
        if(mainPipeId != null){
            mainPipe = template.getMainPipeById(mainPipeId);
        }
        if (mainPipe == null) {
            mainPipe = new MainPipe();
            mainPipe.setId(IdUtil.simpleUUID());

            if (template.getMainPipes() == null) {
                template.setMainPipes(new ArrayList<>());
            }
            template.getMainPipes().add(mainPipe);
        }

        mainPipe.parseLines(lines, template);

        return saveTemplate(template);
    }

    /**
     * 对前端传入的路径进行修正处理
     */
    private List<List<XY>> fixMainPipePath(List<List<XY>> lines){
        //合并同一条线上的多个点
        List<List<XY>> fixed = new ArrayList<>();
        for (List<XY> line : lines) {
            List<XY> fixedLine = new ArrayList<>();
            fixed.add(fixedLine);

            XY p1 = null;
            XY p2 = null;
            for (XY point : line) {
                if (p1 == null) {
                    p1 = point;
                } else if (p2 == null) {
                    p2 = point;
                } else {
                    boolean b = p1.x == p2.x && p2.x == point.x;
                    boolean b1 = p1.y == p2.y && p2.y == point.y;
                    if (b || b1) {
                        fixedLine.remove(p2);
                    } else {
                        p1 = p2;
                    }
                    p2 = point;
                }
                fixedLine.add(point);
            }
        }
        return fixed;
    }

    /**
     * 删除干管
     */
    public DiagramTemplate delMainPipe(String mainPipeId, String templateId) {
        DiagramTemplate template = dataStrategy.getTemplate(templateId);

        if (template.getMainPipes() != null) {
            for (MainPipe mainPipe : template.getMainPipes()) {
                if (mainPipe.getId().equals(mainPipeId)) {
                    template.getMainPipes().remove(mainPipe);
                    break;
                }
            }
        }

        return saveTemplate(template);
    }

    /**
     * 修改干管
     */
    public DiagramTemplate modifyMainPipe(EditRequest.TemplatePropsData propsData, String mainPipeId, String templateId) {
        DiagramTemplate template = dataStrategy.getTemplate(templateId);
        buildTemplate(template);

        MainPipe mainPipe = template.getMainPipeById(mainPipeId);
        if (mainPipe != null) {
            mainPipe.setId(propsData.getId());
            mainPipe.setName(propsData.getName());
            mainPipe.setRemark(propsData.getRemark());
            mainPipe.setPipeType(propsData.getPipeType());
            mainPipe.setBindEquipment(propsData.isBindEquipment());
            mainPipe.setEquipmentTypes(propsData.getEquipTypes());
            mainPipe.setPassbyRels(propsData.getPassbyRels());
            mainPipe.setConnectEquips(propsData.getConnectEquips());
            mainPipe.setRelatedContainers(propsData.getRelatedContainers());
        }

        mainPipe.resetRelatedCons();
        mainPipe.init(template);
        mainPipe.parseLines(mainPipe.getLocationPath(), template);

        return saveTemplate(template);
    }

    /**
     * 修改设备数据过滤条件
     * filter可能是多种类型，通过Map转换
     */
    public DiagramTemplate modifyFilter(Map<String, Object> filter, String compId, String templateId) {
        DiagramTemplate template = dataStrategy.getTemplate(templateId);
        template.init();

        DataFilter dataFilter;
        if (filter != null) {
            dataFilter = contentParser.parseContent(contentParser.toJson(filter), DataFilter.class);
        } else {
            dataFilter = null;
        }

        Container con = template.getContainerById(compId);
        if (con != null) {
            con.setDataFilter(dataFilter);
        } else {
            MainPipe mainPipe = template.getMainPipeById(compId);
            if (mainPipe != null) {
                mainPipe.setDataFilter(dataFilter);
            }
        }

        return saveTemplate(template);
    }

    /**
     * 修改设备打包配置
     */
    public DiagramTemplate modifyPack(EquipPack pack, String containerId, String templateId) {
        DiagramTemplate template = dataStrategy.getTemplate(templateId);
        template.init();

        Container con = template.getContainerById(containerId);
        con.setEquipPack(pack);

        return saveTemplate(template);
    }

    /**
     * 修改容器的动态组配置
     */
    public DiagramTemplate modifyDynGroup(DynGroup dynGroup, String containerId, String templateId) {
        DiagramTemplate template = dataStrategy.getTemplate(templateId);
        template.init();

        Container con = template.getContainerById(containerId);
        con.setDynGroup(dynGroup);

        return saveTemplate(template);
    }

    public String getCopyContent(String compId, String templateId){
        DiagramTemplate template = dataStrategy.getTemplate(templateId);
        template.init();

        Object obj;
        if(StrUtil.isNotBlank(compId)) {
            obj = template.getContainerById(compId);
            if(obj == null){
                obj = template.getMainPipeById(compId);
            }
        } else {
            obj = template;
        }
        return obj != null ? contentParser.toJson(obj) : "";
    }

    public DiagramTemplate setPasteContent(String content, String compId, String templateId){
        DiagramTemplate template = dataStrategy.getTemplate(templateId);
        template.init();

        if(StrUtil.isNotBlank(content)) {
            Map<String, Object> map = contentParser.parseContent(content, Map.class);
            Object o = null;
            if(Container.TYPE.equals(map.get("compType"))){
                o = contentParser.parseContent(content, Container.class);
            } else if(MainPipe.TYPE.equals(map.get("compType"))) {
                o = contentParser.parseContent(content, MainPipe.class);
            } else if(map.containsKey("frame")) {
                o = contentParser.parseContent(content, DiagramTemplate.class);
            }

            if(o != null) {
                if(o instanceof DiagramTemplate){
                    DiagramTemplate other = (DiagramTemplate)o;
                    if(StrUtil.isBlank(compId)) {
                        template.setFrame(other.getFrame());
                        template.setMainPipes(other.getMainPipes());
                        template.setScatteredContainers(other.getScatteredContainers());
                    }
                } else if(o instanceof Container) {
                    Container target = null;
                    if(StrUtil.isNotBlank(compId)) {
                        Container c = template.getContainerById(compId);
                        if(c != null){
                            target = c;
                        }
                    } else {
                      target = template.getFrame();
                    }
                    if(target != null && !target.isEquipmentBox()){
                        Container con = (Container)o;
                        if(template.getContainerById(con.getId()) != null){
                            con.setId(IdUtil.simpleUUID());
                        }
                        target.addComp(con);
                    }
                } else {
                    //暂不支持干管粘贴
                }
            }
        }
        return saveTemplate(template);
    }

}
