package model.DCEL;


import model.Point;

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 DoublyConnectedEdgeList {

    private LinkedList<Node> nodes;
    private LinkedList<Edge> edges;
    private LinkedList<Face> faces;

    public DoublyConnectedEdgeList() {
        this.nodes = new LinkedList<>();
        this.edges = new LinkedList<>();
        this.faces = new LinkedList<>();
    }

    public Node createNode(Point point, String id) {

        Node node = new Node();
        node.setPoint(point);
        node.setID(id);

        return node;
    }

    public Edge createEdge(Node source, Node destination, String id) {

        Edge edge = new Edge();
        Edge twin = new Edge();

        edge.setOrigin(source);
        edge.setID(id);
        edge.setTwin(twin);
        twin.setOrigin(destination);
        twin.setID("#" + id);
        twin.setTwin(edge);

        source.setIncidentEdge(edge);
        destination.setIncidentEdge(twin);

        return edge;
    }

    public Face createFace(Edge outerComponent, Edge innerComponent, String id) {

        Face face = new Face(outerComponent, null);
        face.setID(id);
        Edge tempEdge;

        if (outerComponent != null) {
            tempEdge = outerComponent;
            do {
                tempEdge.setIncidentFace(face);
                tempEdge = tempEdge.getNext();
            } while (!tempEdge.equals(outerComponent));
        }

        if (innerComponent != null) {
            LinkedList<Edge> componentlist;
            componentlist = face.getInnerComponents();
            componentlist.add(innerComponent);
            tempEdge = innerComponent;
            do {
                tempEdge.setIncidentFace(face);
                tempEdge = tempEdge.getNext();
            } while (!tempEdge.equals(innerComponent));
        }

        return face;
    }

    public void createConnection(Edge edge, Edge succ) {
        edge.setNext(succ);
        succ.setPrev(edge);

        edge.getTwin().setPrev(succ.getTwin());
        succ.getTwin().setNext(edge.getTwin());
    }

    public LinkedList<Edge> getEdgesOfInnerComponents(Face face) {

        LinkedList<Edge> list = new LinkedList();
        LinkedList<Edge> innerComponents = face.getInnerComponents();
        Edge it;
        for (Edge e : innerComponents) {
            it = e;
            do {
                list.add(it);
                //System.out.println("Current Edge: "+it.getID()+"\tNext Edge: "+it.getNext().getID());
                it = it.getNext();
            } while (it != e);
        }

        return list;
    }

    public LinkedList<Edge> getEdgesOfOuterComponents(Face face) {

        LinkedList<Edge> list = new LinkedList();
        Edge it = face.getOuterComponent();
        do {
            list.add(it);
            //System.out.println("Current Edge: "+it.getID()+"\tNext Edge: "+it.getNext().getID());
            it = it.getNext();
        } while (it != face.getOuterComponent());

        return list;
    }


    public LinkedList<Edge> getConnectedEdges(Node node) {
        Edge edge = node.getIncidentEdge();
        LinkedList list = new LinkedList();
        do {
            list.add(edge);
            edge = edge.getNext();
        } while (node != edge.getOrigin());
        return list;
    }

    public LinkedList<Node> getNodes() {
        return nodes;
    }

    public void setNodes(LinkedList<Node> nodes) {
        this.nodes = nodes;
    }

    public LinkedList<Edge> getEdges() {
        return edges;
    }

    public void setEdges(LinkedList<Edge> edges) {
        this.edges = edges;
    }

    public LinkedList<Face> getFaces() {
        return faces;
    }

    public void setFaces(LinkedList<Face> faces) {
        this.faces = faces;
    }
}
