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

import com.persagy.adm.diagram.core.DiagramBuilder;
import com.persagy.adm.diagram.core.model.ConnectPoint;
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.XY;
import com.persagy.adm.diagram.core.model.template.MainPipe;
import com.persagy.adm.diagram.core.util.GeomUtil;
import org.locationtech.jts.geom.Point;

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

/**
 * 连线布局计算
 * @author zhaoyk
 */
public class LineLayoutManager {

	private DiagramBuilder diagramBuilder;

	private List<Block> blocks = new ArrayList<>();

	public LineLayoutManager(DiagramBuilder diagramBuilder) {
		this.diagramBuilder = diagramBuilder;
		initBlocks();
	}

	private void initBlocks(){
		for(Object o : diagramBuilder.getEquipMap().values()){
			if (o instanceof DiagramNode) {
				blocks.add(new Block((DiagramNode)o));
			}
		}
	}

	public List<XY> layout(Line line){
		ConnectPoint p1 = line.getFrom();
		ConnectPoint p2 = line.getTo();

		boolean exchange = false;
		//先计算点模型的终点
		if(p1.getEquipmentNode() == null) {
			if(p2.getEquipmentNode() == null) {
				throw new RuntimeException("do not support 2 main pipe connect");
			}

			ConnectPoint tmp = p2;
			p2 = p1;
			p1 = tmp;

			exchange = true;
		}

		LineEnd[] arr = buildLineEnd(p1, p2);
		PathBuilder pb = new PathBuilder(line, arr[0], arr[1], exchange);
		return pb.calcPath(blocks);
	}

	private LineEnd[] buildLineEnd(ConnectPoint p1, ConnectPoint p2) {
		LineEnd[] arr = new LineEnd[2];

		arr[0] = new LineEnd();
		arr[0].setPoint(anchorEmerge(p1));

		if(p2.getHostObj() instanceof EquipmentNode) {
			arr[1] = new LineEnd();
			arr[1].setPoint(anchorEmerge(p2));
		} else if (p2.getHostObj() instanceof MainPipe) {
			Point point1 = GeomUtil.getPoint(p1.getLocation());
			MainPipe mp = (MainPipe) p2.getHostObj();
			XY[] nearLine = null;
			double min = Double.MAX_VALUE;
			for(List<XY> list : mp.getLocationPath()) {
				XY pre = null;
				for(XY xy : list) {
					if(pre != null) {
						//复制坐标
						XY[] line = new XY[]{pre.copy(), xy.copy()};
						//起点终点排序
						LineEnd.orderLine(line);

						//线需要留头
						if(LineEnd.isHorizontal(line)){
							if(line[1].x - line[0].x > LineEnd.offset * 2){
								line[0].x += LineEnd.offset;
								line[1].x -= LineEnd.offset;
							}
						} else {
							if(line[1].y - line[0].y > LineEnd.offset * 2){
								line[0].y += LineEnd.offset;
								line[1].y -= LineEnd.offset;
							}
						}
						//计算点和线段的最短距离
						double distance = point1.distance(GeomUtil.getLine(line));
						if(distance < min){
							min = distance;
							nearLine = line;
						}
					}
					pre = xy;
				}
			}
			arr[1] = new LineEnd();
			arr[1].setLine(nearLine);
		}

		return arr;
	}

	/**
	 * 锚点出线
	 */
	private XY anchorEmerge(ConnectPoint point){
		if(point.getLocation() == null) {
			point.layout();
		}

		XY xy = new XY(point.getLocation());
		switch (point.getAnchorCode().charAt(0)) {
			case 'T':
				xy.y -= LineEnd.offset;
				break;
			case 'B':
				xy.y += LineEnd.offset;
				break;
			case 'L':
				xy.x -= LineEnd.offset;
				break;
			case 'R':
				xy.x += LineEnd.offset;
				break;
			default:
		}
		return xy;
	}

	public List<Block> getBlocks() {
		return blocks;
	}

	public DiagramBuilder getDiagramBuilder() {
		return diagramBuilder;
	}

}
