/**
 * Kartenfächer für magische Informatik
 * zur Behandlung aller Routinen für die Arbeit mit (Teil-)Kartensets
 * Implementierung als einfach verkettete Liste
 * 
 * @author (Ulrich Kiesmüller) 
 * @version (1.4)
 */
 
public class Kartenfaecher
{
    // Variablen - Länge nur für Teilung eines Kartenstapels
    private Karte start;
    private int laenge;

    /**
     * Konstruktor
     */
    public Kartenfaecher()
    {
        // Initialisierung
        start = null;
        laenge = 0;
    }

    /**
     * Methoden zur Kartenstapelbehandlung
     * erst allgemeine, dann trickspezifische
     */
    public void setzeStart(Karte k)
    {
        start = k;
    }
    
    public Karte gibStart()
    {
        return start;
    }
    
    public int gibLaenge()
    {
        return laenge;
    }
		
    // eine Karte wird auf einen bereits existierenden Kartenstapel gelegt
    public void auflegen(Karte k)
    {
        Karte aktuell = start;
        if (start == null) {
            start = k;
            laenge = 1;
        }
        else
            {
                while (aktuell.gibNext() != start) {
                    aktuell = aktuell.gibNext();
                }
                aktuell.setzeNext(k);
                k.setzeNext(start);
                start = k;
                laenge = laenge + 1;
            }
    }
	
    // eine Karte wird unter einen bereits existierenden Kartenstapel gelegt
    public void anlegen(Karte k)
    {
        if (start == null) 
        {
            start = k;
            laenge = 1;
        }
        else
        {
            Karte aktuell = start;
            while (aktuell.gibNext() != start)
            {
                aktuell = aktuell.gibNext();
            }
            aktuell.setzeNext(k);
            k.setzeNext(start);
            laenge = laenge + 1;
        }
    }
	
    // Suchen nach einer bestimmten Karte und deren Entfernung
    // Falls Karte nicht vorhanden, wird nichts gemacht!
    public void entfernen(Karte k)
    {
        if (start == null) return;
        else if (start == k && start.gibNext() == start)
        {
            start = null;
            laenge = 0;
            return;
        }
        else if (start == k && start.gibNext() != start) 
        {
            Karte aktuell = start;
            while (aktuell.gibNext() != start)
            {
                aktuell = aktuell.gibNext();
            }
            aktuell.setzeNext(start.gibNext());
            start = start.gibNext();
            laenge = laenge - 1;
            return;
        }
        else    
        {
            Karte aktuell = start;
            Karte vor = null;
            while (aktuell != k)
            {
                vor = aktuell;
                aktuell = aktuell.gibNext();
            }
            vor.setzeNext(aktuell.gibNext());
            laenge = laenge -1;
            return;
        }
	}
    
    //abheben des Kartenstapels an einer anzugebenden Position
    public void abhebenAn(int pos)
    {
        Karte aktuell = start;
        while (pos > 1) {
            aktuell = aktuell.gibNext();
            pos = pos -1;            
        }
        start = aktuell;
    }
    
    //abheben des Kartenstapels bei einer anzugebenden Karte
    //public void abhebenBei(Karte k)
    //{
    //    Karte aktuell = start;
    //    while (aktuell != k) {
    //        aktuell = aktuell.gibNext();
    //    }
    //    start = aktuell;
    // }
	
    //eine anzugebende Anzahl von Karten einzeln oben am Kartenstapel abziehen und unten wieder anlegen
    public void move(int n)
    {
        Karte aktuell = start;
        while (n > 0)
        {
            aktuell =aktuell.gibNext();
            n = n - 1;
        }
        start = aktuell;
    }
   
    public Kartenfaecher duplizieren()
    {
        Kartenfaecher hilfe = new Kartenfaecher();
        Karte aktuell = this.start;
        Karte temp = new Karte(aktuell.gibFarbe(), aktuell.gibWert());
        hilfe.anlegen(temp);
        aktuell = aktuell.gibNext();
        while (aktuell.gibNext() != start)
        {
            temp = new Karte(aktuell.gibFarbe(), aktuell.gibWert());
            hilfe.anlegen(temp);
            aktuell = aktuell.gibNext();            
        }
        temp = new Karte(aktuell.gibFarbe(), aktuell.gibWert());
        hilfe.anlegen(temp);
        return hilfe;
    }
	
    public Kartenfaecher umdrehen()
    {
        Kartenfaecher hilfe = new Kartenfaecher();
        Karte aktuell = this.start;
        Karte temp = new Karte(aktuell.gibFarbe(), aktuell.gibWert());
        hilfe.auflegen(temp);
        aktuell = aktuell.gibNext();
        while (aktuell.gibNext() != start)
        {
            temp = new Karte(aktuell.gibFarbe(), aktuell.gibWert());
            hilfe.auflegen(temp);
            aktuell = aktuell.gibNext();            
        }
        temp = new Karte(aktuell.gibFarbe(), aktuell.gibWert());
        hilfe.auflegen(temp);
        return hilfe;
    }
    
    //Entfernen der oberen Hälfte eines Kartenstapels
    public Kartenfaecher teilenOben()
    {
        int i = 0;
        int l = gibLaenge()/2;
        while (i < l) {
            entfernen(gibStart());
            i = i + 1;
        }
        return this;
    }

    public void ausgeben()
    {
        if (start == null) return;
        else
        {
            int i = 1;
            Karte aktuell = start;
            while (aktuell.gibNext() != start)
            {
                System.out.print("Die " + i + "-te Karte ist die ");
                aktuell.zeigen();
                System.out.println(".");
                i = i + 1;
                aktuell = aktuell.gibNext();
            }
            System.out.print("Die " + i + "-te Karte ist die ");
            aktuell.zeigen();
            System.out.println(".");
        }
    }
}
