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

import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.persagy.adm.diagram.core.DataStrategy;
import com.persagy.adm.diagram.core.model.Diagram;
import com.persagy.adm.diagram.core.model.DiagramNode;
import com.persagy.adm.diagram.core.model.EquipmentNode;
import com.persagy.adm.diagram.core.model.Line;
import com.persagy.adm.diagram.core.model.base.Container;
import com.persagy.adm.diagram.core.model.base.IDataBind;
import com.persagy.adm.diagram.core.model.template.DiagramTemplate;
import com.persagy.adm.diagram.core.model.template.MainPipe;

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

/**
 * 系统图计算上下文
 * @author zhaoyk
 */
public class CalcContext {

	private Diagram diagram;

	private DiagramTemplate template;

	private DataStrategy dataStrategy;

	private DiagramBuilder diagramBuilder;

	private List<ObjectNode> optionalObjs;

	private List<ObjectNode> optionalRels;

	/**
	 * 当前动态组
	 */
	private CalcGroup currentGroup;

	/**
	 * 记录已经使用的数据id和对应的组件
	 */
	private HashMap<String, IDataBind> equipMap = new HashMap<>();

	/**
	 * 记录已经使用的关系id和对应的连线
	 */
	private HashMap<String, Line> lineMap = new HashMap<>();

	public CalcContext(Diagram diagram) {
		this.diagram = diagram;
		this.template = diagram.getTemplate();

		init();
	}

	private void init() {
		//记录节点中已使用的数据id
		diagram.getNodes().forEach(node -> {
			if (EquipmentNode.TYPE.equals(node.getCompType())) {
				equipMap.put(((EquipmentNode) node).getDataObjectId(), (EquipmentNode)node);
			}
		});
		//记录干管中已使用的数据id
		if(template != null && template.getMainPipes() != null) {
			template.getMainPipes().forEach(mainPipe -> {
				if(StrUtil.isNotBlank(mainPipe.getDataObjectId())) {
					equipMap.put(mainPipe.getDataObjectId(), mainPipe);
				}
			});
		}

		diagram.getLines().forEach(line -> {
			if (StrUtil.isNotBlank(line.getDataObjectId())){
				lineMap.put(line.getDataObjectId(), line);
			}
		});
	}

	public DiagramBuilder getDiagramBuilder() {
		return diagramBuilder;
	}

	public void setDiagramBuilder(DiagramBuilder diagramBuilder) {
		this.diagramBuilder = diagramBuilder;
	}

	public void setCurrentGroup(CalcGroup calcGroup) {
		if(currentGroup != null){
			calcGroup.setParent(currentGroup);
		}
		currentGroup = calcGroup;
	}

	public void clearCurrentGroup(){
		if (currentGroup != null) {
			currentGroup = currentGroup.getParent();
		}
	}

	public <T> T getComp(String id, String type) {
		if(currentGroup != null){
			Object comp = currentGroup.getComp(id);
			if(comp != null) {
				return (T)comp;
			}
		}

		if(Container.TYPE.equals(type)) {
			return (T)template.getContainerById(id);
		} else if(MainPipe.TYPE.equals(type)) {
			return (T)template.getMainPipeById(id);
		} else if(EquipmentNode.TYPE.equals(type)) {
			for(DiagramNode node : diagram.getNodes()) {
				if(node.getId().equals(id)){
					return (T)node;
				}
			}
		} else {
			//TODO 其他类型
		}
		return null;
	}

	public DataStrategy getDataStrategy() {
		return dataStrategy;
	}

	public void setDataStrategy(DataStrategy dataStrategy) {
		this.dataStrategy = dataStrategy;
	}

	public Diagram getDiagram() {
		return diagram;
	}

	public DiagramTemplate getTemplate() {
		return template;
	}

	public HashMap<String, IDataBind> getEquipMap() {
		return equipMap;
	}

	public HashMap<String, Line> getLineMap() {
		return lineMap;
	}

	public List<ObjectNode> getOptionalObjs() {
		return optionalObjs;
	}

	public void setOptionalObjs(List<ObjectNode> optionalObjs) {
		if (optionalObjs == null) {
			optionalObjs = new ArrayList<>(0);
		} else if (equipMap.size() > 0) {
			//去掉已经使用的数据项
			optionalObjs = optionalObjs.stream().filter(obj -> !equipMap.containsKey(obj.get("id").asText())).collect(Collectors.toList());
		}
		this.optionalObjs = optionalObjs;
	}

	public List<ObjectNode> getOptionalRels() {
		return optionalRels;
	}

	public void setOptionalRels(List<ObjectNode> optionalRels) {
		this.optionalRels = optionalRels;
	}

	public String getProjectId() {
		return diagram.getProjectId();
	}

	public String getGroupCode() {
		return diagram.getGroupCode();
	}

}
