/*-
 *  Copyright 2020 Beuth Hochschule für Technik Berlin, Hochschule für Technik Stuttgart
 * 
 *  This file is part of CityDoctor2.
 *
 *  CityDoctor2 is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  CityDoctor2 is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with CityDoctor2.  If not, see <https://www.gnu.org/licenses/>.
 */
package de.hft.stuttgart.citydoctor2.edge;

import java.util.List;

public class HalfEdge2d extends BaseEntity {

	private Coordinate2d start;
	private Coordinate2d end;

	private HalfEdge2d partner;

	private HalfEdge2d next;
	private HalfEdge2d previous;

	public HalfEdge2d(Coordinate2d c1, Coordinate2d c2) {
		this(c1, c2, false);
	}

	public HalfEdge2d(Coordinate2d pStart, Coordinate2d pEnd, boolean setPartner) {
		start = pStart;
		end = pEnd;

		if (setPartner) {

			List<HalfEdge2d> halfEdgesToStart = pStart.getParents(HalfEdge2d.class);
			List<HalfEdge2d> halfEdgesToEnd = pEnd.getParents(HalfEdge2d.class);

			HalfEdge2d pPartner = findPartner(halfEdgesToStart, halfEdgesToEnd);

			if (pPartner != null) {
				setPartner(pPartner);
			}
		} else {
			partner = null;
		}

		addChild(start);
		addChild(end);
	}

	private HalfEdge2d findPartner(List<HalfEdge2d> halfEdgesToStart, List<HalfEdge2d> halfEdgesToEnd) {
		HalfEdge2d pPartner = null;
		for (HalfEdge2d heStart : halfEdgesToStart) {
			for (HalfEdge2d heEnd : halfEdgesToEnd) {
				if (heStart == heEnd) {
					pPartner = heStart;
					if (pPartner.getPartner() == null) {
						return pPartner;
					}
				}
			}
		}
		return pPartner;
	}

	private HalfEdge2d setPartner(HalfEdge2d pPartner) {
		if (partner != null) {
			if (pPartner != null) {
				throw new IllegalStateException("cannot overwrite existing partner-connection");
			} else {
				// remove the existing connection
				partner.partner = null;
				partner = null;
			}
		} else {
			if (pPartner != null) {
				if (pPartner.partner != null) {
					// TODO : das riecht nach einer Ringverzeigerung : 3 Polygonraender treffen
					// aufeinander
					throw new IllegalStateException("cannot overwrite existing partner-connection");
				} else {
					partner = pPartner;
					pPartner.partner = this;
				}
			}
		}
		return pPartner;
	}

	public HalfEdge2d getPartner() {
		return partner;
	}

	public void setNext(HalfEdge2d next) {
		this.next = next;
	}

	public void setPrevious(HalfEdge2d previous) {
		this.previous = previous;
	}

	public Polygon2d getPolygon() {
		List<Polygon2d> parents = getParents(Polygon2d.class);
		if (!parents.isEmpty()) {
			return parents.get(0);
		}
		return null;
	}

	public GmBoundedStraight2d getStraight() {
		return GmBoundedStraight2d.of(start.getPoint(), end.getPoint());
	}

	public Coordinate2d getStart() {
		return start;
	}

	public HalfEdge2d getNext() {
		return next;
	}

	public Coordinate2d getEnd() {
		return end;
	}

	public HalfEdge2d getPrevious() {
		return previous;
	}

	@Override
	public String toString() {
		return "HalfEdge2d [start=" + start + ", end=" + end + "]";
	}

}
