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

import cn.hutool.core.collection.CollUtil;
import com.google.gson.annotations.Expose;
import com.persagy.adm.diagram.core.model.Label;
import com.persagy.adm.diagram.core.model.logic.DataFilter;
import com.persagy.adm.diagram.core.model.logic.DynGroup;
import com.persagy.adm.diagram.core.model.logic.EquipPack;

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

/**
 * 布局容器
 * @author zhaoyk
 */
public class Container extends AbstractComponent implements IContainer {

	public static final String TYPE = "container";

	/**
	 * 设备容器中，如果没有加载到匹配的设备，是否自动隐藏
	 */
	public static final String PROP_AUTO_HIDDEN = "auto_hidden";

	@Expose
	private List<IComponent> children = new ArrayList<>();

	@Expose
	private Layout layout;

	@Expose
	private List<String> equipmentTypes;

	@Expose
	private String remark;

	/**
	 * 设备数据过滤器
	 */
	@Expose
	private DataFilter dataFilter;

	/**
	 * 设备打包
	 */
	@Expose
	private EquipPack equipPack;

	/**
	 * 动态组
	 */
	@Expose
	private DynGroup dynGroup;

	/**
	 * 分组标签
	 */
	private Label groupLabel;

	public Container() {
		this.compType = TYPE;
	}

	@Override
	public Layout getLayout() {
		return layout;
	}

	@Override
	public void setLayout(Layout layout) {
		this.layout = layout;
	}

	@Override
	public void layout() {
		XY p = new XY(layout.marginLeft, layout.marginTop);
		boolean row = layout.getLayout() == Layout.ROW;

		int childMax = 0;
		int idx = 0;
		for(IComponent comp : getArrangedElements()){
			if(comp.isHidden()) {
				if(comp instanceof Container) {
					//给定一个位置，方便计算干管
					comp.setLocation(new XY(p.x, p.y));
					((Container) comp).setSize(new XY(0, 0));
				}
				continue;
			}

			PositionData compPd = comp.getPosition();
			if(compPd == null) {
				compPd = new PositionData();
			}

			if(row){
				if(idx != 0) {
					p.y += layout.spaceV;
				}
			} else {
				if(idx != 0) {
					p.x += layout.spaceH;
				}
			}

			comp.setLocation(new XY(p.x + compPd.paddingLeft, p.y + compPd.paddingTop));
			comp.layout();

			XY childSize = comp.getSize();
			if(row) {
				p.y += childSize.y + compPd.totalPaddingHeight();
				childMax = Math.max(childMax, childSize.x + compPd.totalPaddingWidth());
			} else {
				p.x += childSize.x + compPd.totalPaddingWidth();
				childMax = Math.max(childMax, childSize.y + compPd.totalPaddingHeight());
			}

			idx++;
		}

		size = new XY(p);
		if(row) {
			size.y += layout.marginBottom;
			size.x = layout.marginLeft + childMax + layout.marginRight;
		} else {
			size.x += layout.marginRight;
			size.y = layout.marginTop + childMax + layout.marginBottom;
		}

		if(size.y < position.minH) {
			size.y = position.minH;
		}
		if(size.x < position.minW) {
			size.x = position.minW;
		}

		//自由定位的组件
		for(IComponent comp : getScatteredElements()) {
			comp.layout();

			if(comp.getPosition().getAbsolutePoint() != null) {
				comp.setLocation(comp.getPosition().getAbsolutePoint());
			}
		}
	}

	@Override
	public List<IComponent> getChildren() {
		return children;
	}

	@Override
	public void addComp(IComponent child){
		children.add(child);
		child.setParent(this);

		if(child.getPosition() == null) {
			child.setPosition(child.defaultPosition());
		}
	}

	@Override
	public void removeComp(String childId) {
		for(IComponent o : children) {
			if(o.getId().equals(childId)) {
				children.remove(o);
				return;
			}
		}
	}

	public List<IComponent> getArrangedElements(){
		return children.stream().filter(comp -> !comp.isAbsolutePosition()).collect(Collectors.toList());
	}

	public List<IComponent> getScatteredElements(){
		return children.stream().filter(IComponent::isAbsolutePosition).collect(Collectors.toList());
	}

	@Override
	public List<String> getEquipmentTypes() {
		return equipmentTypes;
	}

	public void setEquipmentTypes(List<String> equipmentTypes) {
		this.equipmentTypes = equipmentTypes;
	}

	public boolean isEquipmentBox() {
		return CollUtil.isNotEmpty(equipmentTypes);
	}

	public String getRemark() {
		return remark;
	}

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

	@Override
	public DataFilter getDataFilter() {
		return dataFilter;
	}

	public void setDataFilter(DataFilter dataFilter) {
		this.dataFilter = dataFilter;
	}

	public EquipPack getEquipPack() {
		return equipPack;
	}

	public void setEquipPack(EquipPack equipPack) {
		this.equipPack = equipPack;
	}

	public DynGroup getDynGroup() {
		return dynGroup;
	}

	public void setDynGroup(DynGroup dynGroup) {
		this.dynGroup = dynGroup;
	}

	public Label getGroupLabel() {
		return groupLabel;
	}

	public void setGroupLabel(Label groupLabel) {
		this.groupLabel = groupLabel;
	}

	public void initParent() {
		List<IComponent> cs = new ArrayList<>(children);
		children.clear();

		for (IComponent comp : cs) {
			addComp(comp);
			if (comp instanceof Container) {
				((Container) comp).initParent();
			}
		}
	}

	public IComponent findComponent(String componentId){
		for(IComponent comp : children) {
			if(comp.getId().equals(componentId)) {
				return comp;
			}
			if(comp instanceof Container) {
				IComponent rtn = ((Container) comp).findComponent(componentId);
				if(rtn != null) {
					return rtn;
				}
			}
		}
		return null;
	}

	@Override
	public PositionData defaultPosition() {
		PositionData data = new PositionData();
		data.minH = data.minW = 200;
		return data;
	}

}
