package graph;
import java.util.List;
import java.util.Arrays;
import java.util.ArrayList;

/**
 * Die Klasse Kante beschreibt die Datenstruktur einer Kante, bestehend aus Startknoten, Gewicht und Zielknoten.
 * Da Kanten innerhalb von Adjazenzlisten und -Matrizen repraesentiert werden, ist diese Klasse eigentlich unnoetig!
 * Sie wurde zum Zweck der Vereinfachung - sozusagen als Zwischenspeicher von Kanten - eingefuehrt.
 * Auch soll sie das Kantengewicht verwalten und Aufschluss darueber geben, ob sie gefaerbt/geloescht ist oder nicht.
 * 
 * @author  Dirk Zechnall, Thomas Schaller
 * @version 28.02.2023 (v7.0)
 * v7.0: Die Kanteninformationen werden in einer Hashmap gespeichert. Daher können beliebige weitere Informationen abgelegt werden.
 
 */
public class Kante extends GraphElement
{
    private Knoten start;
    private Knoten ziel;


    /**
     * Der Konstruktor erstellt eine neue Kante mit Start- und Zielknoten und Kantengewicht.
     * Die Kante ist zu Beginn ungefaerbt.
     *
     * @param  neuerStart  Der neue Startknoten
     * @param  neuerZiel  Der neue Zielknoten
     * @param  neuesGewicht  Das neue Kantengewicht
     */
    public Kante (Knoten neuerStart, Knoten neuerZiel, double neuesGewicht) {
        super();
        set("Gewicht",neuesGewicht);
        set("Markiert", false);
        set("Gelöscht", false);
        set("Farbe", -1);
        setSortierkriterium("Gewicht");
        start = neuerStart;
        ziel = neuerZiel;
    }

    /**
     * Die Methode init initialisiert die Kantenfaerbung (auf unmarkiert)
     */
    protected void init() {
        set("Markiert", false);
        set("Gelöscht", false);
        set("Farbe", -1);
    }

    /** 
     * Liefert einen kurzen Text, der den Wert des Knotens angibt und innerhalb der Kreises 
     * des Knotens angezeigt werden kann.
     * @return Array von Anzeigezeilen (dürfen max. 2 sein)
     */
    public List<String> getKurztext(String[] namen) {
        int l = Math.min(namen.length,2);
        List<String> t = new ArrayList<String>();
        for(int i = 0; i<l; i++) {
            t.add(getString(namen[i]));
        }
        return t;
    }

    /**
     * Liefert eine ausführliche Beschreibung der Werte des Knoten. Wird in dem Tooltext Fenster
     * angezeigt, wenn man mit der Maus über den Knoten geht.
     * @return Array von Anzeigezeilen
     */
    public List<String> getLangtext(String[] namen) {
        int l = namen.length;
        List<String> t = new ArrayList<String>();

        String symbol = "<->";
        if(g.isGerichtet()) symbol = "->";
        if(!start.getInfotext().equals("") && !ziel.getInfotext().equals("")) {
            t.add(start.getInfotext()+" "+symbol+" "+ziel.getInfotext());
        } else {
            t.add("Knoten Nr."+g.getNummer(start)+" "+symbol+" Knoten Nr."+g.getNummer(ziel));
        }

        for(int i = 0; i<l; i++) {
            String w =getString(namen[i]);
            if(!w.isBlank())
                t.add(namen[i]+": "+w);
        }
        return t;
    }

   
    /**
     * Setzt das Gewicht der Kante
     *
     * @param  neuesGewicht  Das neu zu setzende Gewicht
     */
    public void setGewicht(double neuesGewicht) {
        set("Gewicht", neuesGewicht);
    }

    /**
     * Gibt das Gewicht der Kante zurueck
     * 
     * @return  Gewicht der Kante
     */
    public double getGewicht() {
        return getDouble("Gewicht");
    }

    /**
     * Setzt den Startknoten der Kante
     *
     * @param  neuerSatrtKnoten  Der neu zu setzende Startknoten
     */
    public void setStart(Knoten neuerStartKnoten) {
        start = neuerStartKnoten;
    }

    /**
     * Gibt den Startknoten der Kante zurueck
     * 
     * @return  Startknoten
     */
    public Knoten getStart() {
        return start;
    }

    /**
     * Setzt den Zielknoten der Kante
     *
     * @param  neuerZielKnoten  Der neu zu setzende Zielknoten
     */
    public void setZiel(Knoten neuerZielKnoten) {
        ziel = neuerZielKnoten;
    }

    /**
     * Gibt den Zielknoten der Kante zurueck
     * 
     * @return  Zielknoten
     */
    public Knoten getZiel() {
        return ziel;
    }

    /**
     * Gibt Knoten am anderen Ende der Kante zurueck
     * @param k Knoten am ersten Ende der Kante
     * @return  Knoten am anderen Ende
     */
    public Knoten getAnderesEnde(Knoten k) {
        if (k == start) return ziel;
        if (k == ziel) return start;
        return null;
    }

    /**
     * Setzt das markiert-Attribut der Kante
     *
     * @param  wert  Der neu zu setzende markiert-Wert
     */
    public void setMarkiert(boolean wert) {
        set("markiert", wert);
    }

    /**
     * Gibt zurück, ob die Kanten markiert ist
     * 
     * @return  markiert?
     */
    public boolean isMarkiert() {
        return getBoolean("markiert");
    }

    /**
     * Setzt das gelöscht-Attribut der Kante
     *
     * @param  wert  Der neu zu setzende gelöscht-Wert
     */
    public void setGeloescht(boolean wert) {
        set("Gelöscht", wert);
    }

    /**
     * Gibt den gelöscht-Wert der Kante zurueck
     * 
     * @return  gelöscht?
     */
    public boolean isGeloescht() {
        return getBoolean("Gelöscht");
    }

    /**
     * Gibt zurueck, in welcher Farbe die Kante gezeichnet werden soll.
     * Ist die Farbe nicht gesetzt, dann wird eine unmarkierte Kante in Farbe 1 
     * und eine markierte in Farbe 2 gezeichnet.
     * @return Nummer der Farbe
     */
    public int getFarbe() {
        if(getInt("Farbe") == -1) {
            if(isGeloescht()) return 2;
            if(isMarkiert()) return 1;
            return 0;
        }
        return getInt("Farbe");
    }

    /**
     * Setzt die Farbe auf einen bestimmten Farbindex
     * @param farbe Index der Farbe (0-19)
     */
    public void setFarbe(int farbe) {
        if(farbe>=0 && farbe < 20)
            set("Farbe",farbe);
    }

    /**
     * Setzt die Farbe auf die Standardfarbgebung zurück
     */

    public void setStandardFarbe() {
        setFarbe(-1);
    }

   

    /**
     * Die Methode ueberschreibt die Methode toString() und gibt die String-Raepraesentation einer Kante zurueck
     * 
     * @return      String-Raepraesentation der Kante
     */
    @Override
    public String toString() {
        return " --("+getGewicht()+")--> ";
    }

}
