/**
Die Klasse "Angebote" hält eine Liste von Instanzen der Klasse
"Angebot".

Die Verwaltung der Liste funktioniert über eine einfache Verkettung.

Anmerkung: Dieser Code ist nicht zeitoptimiert, um ein hohes Maß an
           Verständlichkeit für den Quelltext zu erreichen.

Interface Angebote:

    public double bestesAngebot( )
    public double bestesAngebot( boolean DeleteIfEmpty )
    public int Count()
    public Angebot GetItemAt( int index )
    public void einfuegen(double Preis, int Anzahl)
**/

class Angebote {

        // ********** public **********

		// Liefert das n-te Angebot. Indexstart bei 0. Wenn der Index die
		// Grenzen überschreitet, wird NULL zurückgegeben.
		// Methode liefert nur dann einen Wert, wenn es sich um eine einfach
		// verkettete KListe handelt
		public Angebot GetItemAt( int index ) {
            Angebot entry = null;
            if (index >= 0) {
		        entry = fFirstEntry;
		        int i = index;
		        while ((entry != null) & (i > 0)) {
		            entry = entry.next;
		            i--;
		        }
		    }
		    return entry;
		}

        /*
        Diese Methode ist zur Abwärtskompatibilität enthalten.
        */
        public double bestesAngebot( ) {
            return bestesAngebot( false );
        }

        /*
        Liefert das billigste verfuegbare Angebot. Dabei wird von der
        Tatsache Gebrauch gemacht, daß die Angebote dem Preis nach
        sortiert sind.
        Der Zähler für die Anzahl wird dabei um 1 dekrementiert.
        Wird (DeleteIfEmpty) übergeben, wird das Angebot gelöscht, wenn
        der Zähler den Wert 0 erreichen sollte.

        Liefert -1 zurück, wenn kein einziges Angebot lieferbar ist
        */
        public double bestesAngebot( boolean DeleteIfEmpty ) {
            double BestSoFar = -1;
            Angebot entry = fFirstEntry;
            Angebot LastEntry = null;

            while ((entry != null) && (BestSoFar == -1)) {
                if (entry.verfuegbarkeit() > 0) {
                    BestSoFar = entry.preis();
                    entry.DecVerfuegbarkeit();

                    // Wenn Angebot nicht mehr vorhanden ist, löschen
                    if ((entry.verfuegbarkeit() == 0) & (DeleteIfEmpty)) {
                        if (LastEntry != null)
                            LastEntry.next = entry.next;
                          else
                            fFirstEntry = entry.next;
                    }
                }
                  else
                {
                    LastEntry = entry;
                    entry = entry.next;
                }
            }

            return BestSoFar;
		}

		// Fuegt ein neues Angebot ein, das in Anzahl Stueck verfuegbar ist.
		// Weil die Liste sortiert ist, wird es entsprechend seinem Preis
		// einsortiert.
		public void einfuegen(double Preis, int Anzahl)
		{
            // Fehlerprüfung
            if (Anzahl > 0) {
		        // wo muß eingefügt werden?
		        int ListPosition = fListPosition( Preis );

                // ein neues Angebot erzeugen
                Angebot NewEntry = new Angebot( Preis, Anzahl );

                if (ListPosition > 0) {
                    // Den Eintrag fetchen, der an dieser Stelle steht
                    Angebot entry = GetItemAt( ListPosition - 1 );

                    // Das neue Angebot "einsortieren"
                    NewEntry.next = entry.next;
                    entry.next = NewEntry;
                }
                  else
                {
                    // Sonderbehandlung, wenn am Anfang der Liste
                    NewEntry.next = fFirstEntry;
                    fFirstEntry = NewEntry;
                }
            }
		}

		// liefert die Anzahl der belegten Einträge im Ordner. Diesen Wert
		// später evtl. in einer Variable buffern.
		public int Count() {
		    // iteratives durchzählen
		    Angebot entry = fFirstEntry;
		    int i = 0;
		    while (entry != null) {
		        entry = entry.next;
		        i++;
		    }
		    return i;
		}

        // ********** private **********

        // hält die Angebote
		private Angebot fFirstEntry;

		// Sucht ein Angebot nach dem Preiskriterium.
		// Es wird der Index zurückgegeben, den ein neues Element mit dem
		// angegebenen Preis erhalten muß.
		// Ist die Liste leer, wird 0 zurückgegeben.
		private int fListPosition( double preis ) {
		    int result = 0;
		    if (Count() > 0) {
		        Angebot entry = fFirstEntry;
		        // erhöhen, wenn noch ein Angebot existiert, und dieses Angebot
		        // einen höheren Preis hat.
                while ((entry != null) && (entry.preis() < preis)) {
                    result++;
                    entry = entry.next;
                }
		    }
  		    return result;
		}

}

