package com.persagy.adm.diagram.demo;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.persagy.adm.diagram.entity.DiagramType;
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.legend.Legend;
import com.persagy.adm.diagram.core.model.template.DiagramTemplate;
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.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * 测试开发使用的io策略实现类
 *
 * @author zhaoyk
 */
@Service
@Qualifier("demo")
public class DemoDataStrategy implements DataStrategy {

    @Autowired
    private ContentParser parser;

    @Override
    public List<DiagramType> getDiagramTypes() {
        List<DiagramType> types = new ArrayList<>();

        readFiles((majCode, sysCode, typeCode, typeDir) -> {
            DiagramType diagramType = new DiagramType();
            diagramType.setMajor(majCode);
            diagramType.setDSystem(sysCode);
            diagramType.setCode(typeCode);
            diagramType.setName(typeDir.getName());

            types.add(diagramType);
            return null;
        });

        return types;
    }

    /* 模板部分 */
    private static final String DIR_TEMPLATE = "store/template/";

    @Override
    public List<DiagramTemplate> getTemplates() {
        List<DiagramTemplate> rtn = new ArrayList<>();

        readFiles((majCode, sysCode, typeCode, typeDir) -> {
            File[] files = typeDir.listFiles();
            if (files != null) {
                for (File f : files) {
                    try {
                        DiagramTemplate template = parser.parseContent(FileUtil.readUtf8String(f), DiagramTemplate.class);
                        rtn.add(template);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
            return null;
        });

        return rtn;
    }

    private <T> T readFiles(Handler<T> handler) {
        File dir = new File(DIR_TEMPLATE);
        File[] majList = dir.listFiles();
        if (majList == null) {
            return null;
        }

        for (File fm : majList) {
            String majCode = fm.getName().substring(0, 2);

            File[] sysList = fm.listFiles();
            if (sysList == null) {
                continue;
            }

            for (File fs : sysList) {
                String sysCode = majCode + fs.getName().substring(0, 2);
                File[] typeList = fs.listFiles();
                if (typeList != null) {
                    for (File ft : typeList) {
                        String typeCode = sysCode + "_" + ft.getName();

                        T result = handler.handle(majCode, sysCode, typeCode, ft);
                        if (result != null) {
                            return result;
                        }
                    }
                }
            }
        }

        return null;
    }

    interface Handler<T> {
        T handle(String majCode, String sysCode, String typeCode, File typeDir);
    }

    @Override
    public List<DiagramTemplate> getTemplates(String diagramType) {
        List<DiagramTemplate> rtn = new ArrayList<>();

        readFiles((majCode, sysCode, typeCode, typeDir) -> {
            if (diagramType.equals(typeCode)) {
                File[] files = typeDir.listFiles();
                if (files != null) {
                    for (File f : files) {
                        try {
                            DiagramTemplate template = parser.parseContent(FileUtil.readUtf8String(f), DiagramTemplate.class);
                            rtn.add(template);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
            return null;
        });

        return rtn;
    }

    @Override
    public DiagramTemplate saveTemplate(DiagramTemplate template) {
        return readFiles((majCode, sysCode, typeCode, typeDir) -> {
            if (typeCode.equals(template.getDiagramType())) {
                try {
                    String json = parser.toJson(template);
                    FileUtil.writeUtf8String(json, new File(typeDir, template.getName() + ".json"));
                    return parser.parseContent(json, DiagramTemplate.class);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
            return null;
        });
    }

    @Override
    public boolean deleteTemplate(String templateId) {
        File del = readFiles((majCode, sysCode, typeCode, typeDir) -> {
            File[] files = typeDir.listFiles();
            if (files != null) {
                for (File f : files) {
                    try {
                        DiagramTemplate template = parser.parseContent(FileUtil.readUtf8String(f), DiagramTemplate.class);
                        if (template.getId().equals(templateId)) {
                            f.delete();
                            return f;
                        }
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                }
            }
            return null;
        });
        return del != null;
    }

    @Override
    public DiagramTemplate getTemplate(String templateId) {
        return readFiles((majCode, sysCode, typeCode, typeDir) -> {
            File[] files = typeDir.listFiles();
            if (files != null) {
                for (File f : files) {
                    try {
                        DiagramTemplate template = parser.parseContent(FileUtil.readUtf8String(f), DiagramTemplate.class);
                        if (template.getId().equals(templateId)) {
                            return template;
                        }
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                }
            }
            return null;
        });

    }


    /**
     * 图例部分
     */
    private static final String DIR_LEGEND = "store/legend/";

    @Override
    public List<Legend> getLegends(String systemCode) {
        File file = new File(DIR_LEGEND, systemCode + ".json");
        if (!file.exists()) {
			FileUtil.writeUtf8String("[]", file);
		}

        Legend[] legends = parser.parseContent(FileUtil.readUtf8String(file), Legend[].class);
        ArrayList<Legend> list = new ArrayList<>();
        Collections.addAll(list, legends);
        return list;
    }

    @Override
    public Legend saveLegend(Legend legend, String systemCode) {
        List<Legend> list = getLegends(systemCode);

        if (StrUtil.isBlank(legend.getId())) {
            legend.setId(IdUtil.simpleUUID());
            list.add(legend);
        } else {
            for (int i = 0; i < list.size(); i++) {
                Legend l = list.get(i);
                if (l.getId().equals(legend.getId())) {
                    list.set(i, legend);
                    break;
                }
            }
        }

        File file = new File(DIR_LEGEND, systemCode + ".json");
        FileUtil.writeUtf8String(parser.toJson(list), file);

        return legend;
    }

    @Override
    public boolean deleteLegend(String legendId, String systemCode) {
        List<Legend> list = getLegends(systemCode);

        boolean flag = false;
        for (int i = 0; i < list.size(); i++) {
            Legend l = list.get(i);
            if (l.getId().equals(legendId)) {
                list.remove(l);
                flag = true;
                break;
            }
        }

        File file = new File(DIR_LEGEND, systemCode + ".json");
        FileUtil.writeUtf8String(parser.toJson(list), file);

        return flag;
    }

    @Override
    public Legend getLegend(String legendId, String systemCode) {
        List<Legend> list = getLegends(systemCode);
        for (Legend legend : list) {
            if (legend.getId().equals(legendId)) {
				return legend;
			}
        }
        return null;
    }

    @Override
    public List<Legend> getLegendsForEquipment(String equipmentType) {
        String systemCode = equipmentType.substring(0, 4);

        List<Legend> rtn = new ArrayList<>();
        List<Legend> list = getLegends(systemCode);
        for (Legend legend : list) {
            if (legend.getEquipmentTypes() != null && legend.getEquipmentTypes().contains(equipmentType)) {
				rtn.add(legend);
			}
        }

        return rtn;
    }


    /** 系统图部分 */
    private static final String DIR_DIAGRAM = "store/diagram/";

    @Override
    public List<Diagram> getDiagrams(String projectId, String systemId, String groupCode) {
        return getDiagrams(null, projectId, systemId, groupCode, null);
    }

    @Override
    public List<Diagram> getDiagrams(String diagramType, String projectId, String systemId, String groupCode, String name) {
        ArrayList<Diagram> diagrams = new ArrayList<>();

        File dir = new File(DIR_DIAGRAM);
        File[] list = dir.listFiles();
        if (list != null) {
            for (File f : list) {
                Diagram diagram = parser.parseContent(FileUtil.readUtf8String(f), Diagram.class);
                if (projectId.equals(diagram.getProjectId())) {
                    if (StrUtil.isNotBlank(groupCode) && !groupCode.equals(diagram.getGroupCode())) {
						continue;
					}
                    if (StrUtil.isNotBlank(diagramType) && !diagramType.equals(diagram.getType())) {
						continue;
					}
                    if (StrUtil.isNotBlank(systemId) && !systemId.equals(diagram.getSystemId())) {
						continue;
					}

                    diagrams.add(diagram);
                }
            }
        }

        return diagrams;
    }

    @Override
    public Diagram saveDiagram(Diagram diagram) {
        File file = new File(DIR_DIAGRAM, diagram.getId() + ".json");
        FileUtil.writeUtf8String(parser.toJson(diagram), file);

        return diagram;
    }

    @Override
    public boolean deleteDiagram(String diagramId) {
        File dir = new File(DIR_DIAGRAM);
        File[] list = dir.listFiles();
        if (list != null) {
            for (File f : list) {
                String fn = f.getName();
                fn = fn.substring(0, fn.lastIndexOf('.'));
                if (diagramId.equals(fn)) {
                    f.delete();
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public Diagram getDiagram(String diagramId) {
        File file = new File(DIR_DIAGRAM, diagramId + ".json");
        if (file.exists()) {
			return parser.parseContent(FileUtil.readUtf8String(file), Diagram.class);
		}
        return null;
    }


    //系统图数据加载
    @Autowired
    private BdtpDataService dataService;

    @Override
    public List<ObjectNode> loadObjectsByType(List<String> equipmentTypes, String projectId, String systemId, String groupCode) {
        BdtpRequest req = BdtpRequest.getCurrent();
        req.setProjectId(projectId);
        req.setGroupCode(groupCode);
        return dataService.queryObjectsByType(req, equipmentTypes, systemId);
    }

    @Override
    public List<ObjectNode> loadRelationsByType(List<String[]> relationTypes, List<String> objectIds, String projectId, String groupCode) {
        BdtpRequest req = BdtpRequest.getCurrent();
        req.setProjectId(projectId);
        req.setGroupCode(groupCode);
        return dataService.queryRelsByTypeAndObj(req, relationTypes, objectIds);
    }

    @Override
    public List<ObjectNode> loadObjectsById(List<String> objectIds, String projectId, String groupCode) {
        BdtpRequest req = BdtpRequest.getCurrent();
        req.setProjectId(projectId);
        req.setGroupCode(groupCode);
        return dataService.queryObjectsById(req, objectIds);
    }

    @Override
    public List<ObjectNode> loadRelationsById(List<String> relationIds, String projectId, String groupCode) {
        //TODO
        return null;
    }

    @Override
    public List<ObjectNode> loadSystemInstance(String projectId, String groupCode) {
        return null;
    }

    @Override
    public List<ObjectNode> loadMajorSystemInstance() {
        return null;
    }

    @Override
    public List<ObjectNode> loadSystemTypeTemplate(Diagram diagram) {
        return null;
    }

    // @Override
    public boolean updateState(String state, String id) {
        return false;
    }
}
