package com.persagy.adm.diagram.manage;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.IdUtil;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.persagy.adm.diagram.core.ContentParser;
import com.persagy.adm.diagram.core.model.base.*;
import com.persagy.adm.diagram.core.model.logic.*;
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.EditRequest;
import com.persagy.adm.diagram.core.DataStrategy;
import com.persagy.adm.diagram.core.model.template.ContainerRefPoint;
import com.persagy.adm.diagram.core.model.template.DiagramTemplate;
import com.persagy.adm.diagram.core.model.template.MainPipe;
import com.persagy.adm.diagram.core.model.template.MainPipePoint;
import com.persagy.adm.diagram.frame.BdtpRequest;
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.LinkedList;
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 = dataStrategy.saveTemplate(template);
        buildTemplate(template);
        return template;
    }

    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 addMainPipe(List<List<XY>> lines, String templateId) {
        //合并同一条线上的多个点
        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);
            }
        }

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

        List<ContainerRefPoint> allRefPoints = new ArrayList<>();

        LinkedList<Container> cons = new LinkedList<>();
        cons.add(template.getFrame());
        while (cons.size() > 0) {
            Container con = cons.removeFirst();
            //不使用frame和自由定位容器做定位
            if (con.getParent() != null && !con.isAbsolutePosition()) {
                allRefPoints.addAll(ContainerRefPoint.getRefPoints(con, con.locationToRoot()));
            }

            for (IComponent comp : con.getChildren()) {
                if (comp instanceof Container) {
                    cons.add((Container) comp);
                }
            }
        }

        MainPipe mainPipe = new MainPipe();
        //TODO
        mainPipe.setId(IdUtil.simpleUUID());

        for (List<XY> line : fixed) {
            List<MainPipePoint> ps = new ArrayList<>();
            mainPipe.getPath().add(ps);

            for (XY point : line) {
                double min = Double.MAX_VALUE;
                ContainerRefPoint targetRp = null;
                for (ContainerRefPoint rp : allRefPoints) {
                    double d = distance(point, rp.getLocation());
                    if (d < min) {
                        min = d;
                        targetRp = rp;
                    }
                }
                MainPipePoint mp = new MainPipePoint();
                mp.setContainerId(targetRp.getContainerId());
                mp.setRefPointName(targetRp.getName());
                mp.setOffset(new XY(point.x - targetRp.getLocation().x, point.y - targetRp.getLocation().y));
                ps.add(mp);
            }
        }
        if (template.getMainPipes() == null) {
            template.setMainPipes(new ArrayList<>());
        }
        template.getMainPipes().add(mainPipe);

        return saveTemplate(template);
    }

    private double distance(XY p1, XY p2) {
        return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2));
    }

    /**
     * 删除干管
     */
    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);

        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());
        }

        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);
    }

}
