package model.DCEL;

import java.util.LinkedList;

/**
 * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
 *
 * @Author: Armin Wolf
 * @Email: a_wolf28@uni-muenster.de
 * @Date: 30.05.2017.
 */
public class Face {

    private LinkedList<Edge> innerComponents;
    private Edge outerComponent;
    private String id;

    public Face() {
        this.outerComponent = null;
        this.innerComponents = new LinkedList<>();
    }

    public Face(Edge outerComponent, LinkedList<Edge> innerComponents) {
        this.outerComponent = outerComponent;
        if (innerComponents != null) {
            this.innerComponents = innerComponents;
        } else {
            this.innerComponents = new LinkedList<>();

        }

    }

    public LinkedList<Edge> getInnerComponents() {
        return innerComponents;
    }

    public void setInnerComponents(LinkedList<Edge> innerComponents) {
        this.innerComponents = innerComponents;
    }

    public Edge getOuterComponent() {
        return outerComponent;
    }

    public void setOuterComponent(Edge outerComponent) {
        this.outerComponent = outerComponent;
    }

    public Face insertEdge(Edge edgeWithSameDestination, Edge edgeToMySource) {

        if (edgeWithSameDestination.getIncidentFace().equals(this) || edgeToMySource.getIncidentFace()
                .equals(this)) {
            LinkedList<Edge> components = new LinkedList<Edge>();
            for (Edge e : innerComponents) {
                components.add(e);
            }
            Face face = new Face(getOuterComponent(), components);
            Edge edge = new Edge();
            Edge twin = new Edge();

            edge.setOrigin(edgeWithSameDestination.getOrigin());
            edge.setTwin(twin);
            edge.setNext(edgeToMySource);
            edge.setPrev(edgeWithSameDestination.getPrev());

            twin.setOrigin(edgeToMySource.getOrigin());
            twin.setTwin(edge);
            twin.setNext(edgeWithSameDestination);
            twin.setPrev(edgeToMySource.getPrev());

            Edge tempEdge = edge.getNext();
            Edge tempTwin = twin.getNext();
            //kreis umlaufen um festzustellen welche fläche kleiner ist
            while ((tempEdge.equals(edge) == false) && (tempTwin.equals(twin) == false)) {
                tempEdge = tempEdge.getNext();
                tempTwin = tempTwin.getNext();
            }

            if (tempEdge.equals(edge)) {
                setOuterComponent(twin);
                twin.setIncidentFace(this);
                face.setOuterComponent(edge);
            } else {
                setOuterComponent(edge);
                edge.setIncidentFace(this);
                face.setOuterComponent(twin);
            }

            LinkedList<Edge> bla = new LinkedList<Edge>();
            Edge iterEdge = face.getOuterComponent();
            bla.add(face.getOuterComponent());

            while (iterEdge.hasNext()) {
                bla.add(iterEdge.getNext());
                iterEdge = iterEdge.getNext();
            }

            for (Edge e : face.getInnerComponents()) {
                iterEdge = e;
                while (iterEdge.hasNext()) {
                    bla.add(iterEdge.getNext());
                    iterEdge = iterEdge.getNext();
                }
            }

            for (Edge e : bla) {
                e.setIncidentFace(face);
            }
            return face;
        } else {
            throw new IllegalArgumentException(
                    "Die angegebenen Kanten haben keinen zusammenhang mit der Fläche!");
        }

    }

    public String getID() {
        return this.id;
    }

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