package liste;

/**
 * Eine ArrayList-artige Listenimplementation
 * 
 * @author Rainer Helfrich
 * @version Oktober 2020
 */
public class ListeMitArray<T> extends Liste<T>
{
    /**
     * Das Array, das die Nutzdaten speichert
     */
    private Object[] daten;
    
    /**
     * Zähler, der angibt, wie viele der Werte im Array gültig sind
     */
    private int anzahl;

    /**
     * Erzeugt eine neue Liste
     */
    public ListeMitArray()
    {
        daten = new Object[10];
        anzahl = 0;
    }
    
    /**
     * Gibt die Anzahl der Elemente der Liste zurück
     */
    public int laenge()
    {
        return anzahl;
    }
    
    /**
     * Gibt die Listenelemente hintereinander auf der Konsole aus.
     */
    public void ausgeben()
    {
        for (int i = 0; i < anzahl; i++)
        {   
            System.out.print(daten[i] + " ");
        } 
        System.out.println();
    }
    
    /**
     * Fügt einen neuen Wert an einer gewünschten Stelle in der Liste ein.
     * @param index Die Stelle, an der der neue Wert stehen soll (0 <= index <= laenge())
     * @param val Der einzufügende Wert
     */
    public void einfuegenBei(int index, T val)
    {
        if (index >= 0 && index <= anzahl)
        {
            groessePruefen();
            for (int i = anzahl; i > index; i--)
            {
                daten[i] = daten[i-1];
            }
            daten[index] = val;
            anzahl++;
        }
    }
    
    /**
     * Hängt einen neuen Wert hinten an die Liste an.
     * @param val Der anzuhängende Wert
     */
    public void anhaengen(T val)
    {
        einfuegenBei(anzahl, val);
    }
    
    /**
     * Gibt den n-ten Wert (0-basierte Zählweise) der Liste zurück.
     * @param n Der Index des gewünschten Elements
     * @return Den n-ten Wert
     */
    public T getNtenWert(int n)
    {
        if (n >= 0 && n < anzahl)
        {
            return (T)daten[n];
        }
        else
        {
            return null;
        }
    }
    
    private void groessePruefen()
    {
        if (anzahl >= daten.length)
        {
            Object[] tmp = new Object[daten.length*2];
            System.arraycopy(daten, 0, tmp, 0, anzahl);
            daten = tmp;
        }
    }
    
    /**
     * Entfernt das Element, das am gegebenen Index steht, aus der Liste.
     * @param index Die Stelle, von der der Wert entfernt werden soll.
     */
    public void entferneBei(int index)
    {
        if (index >= 0 && index < anzahl)
        {
            for (int i = index; i < anzahl-1; i++)
            {
                daten[i] = daten[i+1];
            }
            anzahl--;
        }
    }
        
    /**
     * Gibt zurück, ob ein Wert sich in der Liste befindet
     * @param val Der zu suchende Wert
     * @return true, wenn der Wert enthalten ist; false sonst
     */
    public boolean enthaelt(T val)
    {
        for (int i = 0; i < anzahl; i++)
        {
            if (daten[i].equals(val))
            {
                return true;
            }
        }
        return false;
    }
    
    /**
     * Gibt zurück, ob die Liste leer ist.
     * @return true, wenn die Liste keine Elemente enthält; false sonst
     */
    public boolean istLeer()
    {
        return anzahl == 0;
    }
}
