package com.persagy.adm.diagram.core;

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.model.Diagram;
import com.persagy.adm.diagram.core.model.EquipmentNode;
import com.persagy.adm.diagram.core.model.Label;
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.legend.Legend;
import com.persagy.adm.diagram.core.model.virtual.PackNode;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * 处理系统图的计算逻辑
 * @author zhaoyk
 */
public class DiagramBuilder {

	private Diagram diagram;

	private DataStrategy dataStrategy;

	private HashMap<String, List<Legend>> legendsCache = new HashMap<>();

	public DiagramBuilder(Diagram diagram, DataStrategy dataStrategy) {
		this.diagram = diagram;
		this.dataStrategy = dataStrategy;
	}

	public void addEquipNode(Container con, ObjectNode obj){
		EquipmentNode node = new EquipmentNode();
		node.setId(IdUtil.simpleUUID());
		node.setObjId(obj.get("id").asText());
		node.setObjClassCode(DiagramBuilder.getClassCode(obj));
		node.setDataObject(obj);

		initNode(node, DiagramBuilder.getName(obj), con);

		Legend legend = findLegend(node.getObjClassCode(), obj);
		if(legend != null) {
			node.setLegendId(legend.getId());
			node.setLegend(legend);
		}
	}

	private void initNode(EquipmentNode node, String name, Container con){
		con.addComp(node);
		node.setContainerId(con.getId());
		node.setLayoutIndex(con.getChildren().size() - 1);

		Label label = new Label();
		label.setContent(name);
		node.setLabel(label);

		diagram.getNodes().add(node);
	}

	public void addPackData(Container con, ObjectNode obj){
		PackNode pn = null;
		String classCode = getClassCode(obj);
		Legend legend = null;
		if(!con.getEquipPack().isPackByType()) { //single
			String packName = con.getEquipPack().getPackName();
			if(StrUtil.isBlank(packName))
				packName = getTypeName(classCode);
			if(con.getChildren().size() == 0)
				pn = newPackNode(PackNode.SINGLE_PACK, con, packName);
			else
				pn = (PackNode) con.getChildren().get(0);
			if(con.getEquipPack().getLegendId() != null)
				legend = dataStrategy.getLegend(con.getEquipPack().getLegendId(), classCode.substring(0, 4));
		} else { //group
			for(IComponent comp : con.getChildren()) {
				PackNode item = (PackNode) comp;
				if(item.getObjClassCode().equals(classCode)){
					pn = item;
					break;
				}
			}
			if(pn == null)
				pn = newPackNode(classCode, con, getTypeName(classCode));
		}

		if(legend == null)
			legend = findLegend(classCode, null);
		if(legend != null) {
			pn.setLegendId(legend.getId());
			pn.setLegend(legend);
		}

		pn.add(classCode);
	}

	private PackNode newPackNode(String objClsCode, Container con, String packName){
		PackNode pn = new PackNode();
		pn.setId(IdUtil.simpleUUID());
		pn.setObjClassCode(objClsCode);

		initNode(pn, packName, con);

		return pn;
	}

	private String getTypeName(String classCode){
		//TODO
		return classCode;
	}

	private Legend findLegend(String classCode, ObjectNode obj){
		List<Legend> legends = legendsCache.get(classCode);
		if (legends == null) {
			legends = dataStrategy.getLegendsForEquipment(classCode);
			if (legends == null)
				legends = new ArrayList<>();
			legendsCache.put(classCode, legends);
		}
		if(legends.size() > 0) {
			Legend l0 = null, l1 = null;
			for(Legend legend : legends) {
				//系统图类型匹配
				boolean typeMatch = CollUtil.isNotEmpty(legend.getDiagramTypes()) && legend.getDiagramTypes().contains(diagram.getType());
				//过滤条件匹配
				boolean filterMatch;
				if(obj != null && legend.getDataFilter() != null)
					filterMatch = legend.getDataFilter().filter(obj);
				else
					filterMatch = true;

				if(typeMatch && filterMatch)
					return legend;

				if(typeMatch && l0 == null)
					l0 = legend;
				if(filterMatch && l1 == null)
					l1 = legend;
			}
			if(l0 != null)
				return l0;
			if(l1 != null)
				return l1;

			return legends.get(0); //没有优先匹配的话取第一个
		}

		//返回一个缺省图例
		Legend l = new Legend();
		l.setWidth(100);
		l.setHeight(100);
		return l;
	}

	public static String getName(ObjectNode obj){
		String name = null;
		if(obj.get("localName") != null)
			name = obj.get("localName").asText();
		if(StrUtil.isBlank(name))
			name = obj.get("name").asText();
		return name;
	}

	public static String getClassCode(ObjectNode obj){
		if(obj.get("classCode") != null)
			return obj.get("classCode").asText();
		return null;
	}

}
