package com.persagy.adm.diagram.core.model;

import cn.hutool.core.util.StrUtil;
import com.google.gson.annotations.Expose;
import com.persagy.adm.diagram.core.line.LineLayoutManager;
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.base.XY;
import com.persagy.adm.diagram.core.model.logic.CalcContext;
import com.persagy.adm.diagram.core.model.template.DiagramTemplate;
import com.persagy.adm.diagram.core.model.template.MainPipe;

import java.util.*;

/**
 * 系统图
 * @author zhaoyk
 */
public class Diagram {

	@Expose(serialize = false)
	private String id;

	/**
	 * 系统图名称
	 */
	@Expose(serialize = false)
	private String name;

	/**
	 * 描述信息
	 */
	@Expose(serialize = false)
	private String remark;

	/**
	 * 系统图类型编码
	 */
	@Expose(serialize = false)
	private String type;

	/**
	 * 引用的模板id
	 */
	@Expose(serialize = false)
	private String templateId;

	/**
	 * 所属的系统类型
	 */
	@Expose(serialize = false)
	private String system;

	/**
	 * 项目id
	 */
	@Expose(serialize = false)
	private String projectId;

	/**
	 * 对应的系统实例id
	 */
	@Expose(serialize = false)
	private String systemId;

	/**
	 * 集团编码
	 */
	@Expose(serialize = false)
	private String groupCode;

	/**
	 * 其他字段信息
	 */
	@Expose(serialize = false)
	private Map<String, Object> extraProps;

	/**
	 * 连线列表
	 */
	@Expose
	private List<Line> lines = new ArrayList();

	@Expose
	private DiagramTemplate template;

	@Expose
	private XY size;

	/**
	 * 节点列表，运行时&显示态数据结构
	 */
	private List<DiagramNode> nodes = new ArrayList<>();

	public void init(){
		if (template != null) {
			template.init();

			List<Container> containers = template.getContainers();
			for(Container con : containers) {
				if(con.isEquipmentBox()) {
					for(IComponent comp : con.getChildren()) {
						if(comp instanceof DiagramNode){
							nodes.add((DiagramNode) comp);
						}
					}
				}
			}
		}

//		nodes.sort(new Comparator<DiagramNode>() {
//			@Override
//			public int compare(DiagramNode o1, DiagramNode o2) {
//				return o1.getLayoutIndex() - o2.getLayoutIndex();
//			}
//		});
//		for (DiagramNode node : nodes) {
//			Container con = template.getContainerById(node.getContainerId());
//			if (con != null) {
//				con.addComp(node);
//			}
//		}
	}

	public void layout(CalcContext context){
		if(template != null) {
			template.layout(new XY(0, 0));

			size = template.getFrame().getSize();
		}

		layoutLines(context);
	}

	public void layoutLines(CalcContext context) {
		LineLayoutManager lineLayoutManager = new LineLayoutManager(context);
		for(Line line : lines) {
			line.layout(lineLayoutManager);
		}
	}

	public void layoutLine(String lineId, CalcContext context){
		for(Line line : lines) {
			if(lineId.equals(line.getId())) {
				line.layout(new LineLayoutManager(context));
				break;
			}
		}
	}

	public void clearLayout(){
		if(template != null) {
			template.clearLayout();
		}

		for(Line line : lines) {
			line.clearLayout();
		}

		this.size = null;
	}

	public void toAbsoluteLocation(){
		for (DiagramNode node : nodes) {
			node.setLocation(node.locationToRoot());
			if(node instanceof EquipmentNode) {
				EquipmentNode en = (EquipmentNode) node;
				if(en.getAnchorLocations() != null) {
					for(XY point : en.getAnchorLocations().values()){
						point.x += en.getLocation().x;
						point.y += en.getLocation().y;
					}
				}
				if(en.getLabel() != null) {
					XY point = en.getLabel().getLocation();
					point.x += en.getLocation().x;
					point.y += en.getLocation().y;
				}
			}
		}
	}

	public List<String> getObjIds(){
		List<String> ids = new ArrayList<>();
		for(DiagramNode node : nodes) {
			if(EquipmentNode.TYPE.equals(node.getCompType())) {
				ids.add(((EquipmentNode) node).getDataObjectId());
			}
		}
		if(template != null && template.getMainPipes() != null) {
			for(MainPipe mainPipe : template.getMainPipes()) {
				if(mainPipe.isBindEquipment() && StrUtil.isNotBlank(mainPipe.getDataObjectId())) {
					ids.add(mainPipe.getDataObjectId());
				}
			}
		}
		return ids;
	}

	public List<String> getRelIds(){
		List<String> ids = new ArrayList<>();
		for(Line line : lines) {
			if(StrUtil.isNotBlank(line.getDataObjectId())) {
				ids.add(line.getDataObjectId());
			}
		}
		return ids;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getRemark() {
		return remark;
	}

	public void setRemark(String remark) {
		this.remark = remark;
	}

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}

	public String getTemplateId() {
		return templateId;
	}

	public void setTemplateId(String templateId) {
		this.templateId = templateId;
	}

	public List<DiagramNode> getNodes() {
		return nodes;
	}

	public void setNodes(List<DiagramNode> nodes) {
		this.nodes = nodes;
	}

	public List<Line> getLines() {
		return lines;
	}

	public void setLines(List<Line> lines) {
		this.lines = lines;
	}

	public String getSystem() {
		return system;
	}

	public void setSystem(String system) {
		this.system = system;
	}

	public String getProjectId() {
		return projectId;
	}

	public void setProjectId(String projectId) {
		this.projectId = projectId;
	}

	public String getSystemId() {
		return systemId;
	}

	public void setSystemId(String systemId) {
		this.systemId = systemId;
	}

	public String getGroupCode() {
		return groupCode;
	}

	public void setGroupCode(String groupCode) {
		this.groupCode = groupCode;
	}

	public Object getExtraProp(String propName) {
		return extraProps != null ? extraProps.get(propName) : null;
	}

	public void setExtraProp(String propName, Object propValue) {
		if(extraProps == null) {
			extraProps = new HashMap<>();
		}

		if(propValue != null) {
			extraProps.put(propName, propValue);
		} else {
			extraProps.remove(propName);
		}
	}

	public DiagramTemplate getTemplate() {
		return template;
	}

	public void setTemplate(DiagramTemplate template) {
		this.template = template;
	}

	public String[] getLegendIds() {
		HashSet<String> ids = new HashSet<>();
		nodes.forEach(node -> {
			if(node instanceof EquipmentNode) {
				String legendId = ((EquipmentNode) node).getLegendId();
				if(StrUtil.isNotBlank(legendId)){
					ids.add(legendId);
				}
			}
		});
		return ids.toArray(new String[ids.size()]);
	}

}
