package de.duehl.swing.ui.elements.navigator;

/*
 * Copyright 2022 Christian Dühl. All rights reserved.
 *
 * This program is free software. You can redistribute it and/or
 * modify it under the same terms as perl:
 *
 * general:  http://dev.perl.org/licenses/
 * GPL:      http://dev.perl.org/licenses/gpl1.html
 * artistic: http://dev.perl.org/licenses/artistic.html
 */

import java.util.List;

/**
 * Diese Klasse stellt die anzuzeigenden und zu bearbeitenden Daten, zwischen denen navigiert wird
 * dar.
 *
 * @version 1.01     2022-06-01
 * @author Christian Dühl
 */

public class NavigatedData<Data> {

    /** Liste der anzuzeigenden und zu bearbeitenden Daten, zwischen denen navigiert wird. */
    private final List<Data> uiDatasets;

    /** Aktuelle Index der angezeigten Daten. */
    private int actualShownIndex;

    /**
     * Konstruktor.
     *
     * @param uiDatasets
     *            Liste der anzuzeigenden und zu bearbeitenden Daten, zwischen denen navigiert
     *            wird.
     */
    public NavigatedData(List<Data> uiDatasets) {
        this.uiDatasets = uiDatasets;
        actualShownIndex = 0;
    }

    /** Gibt die Anzahl der Datensätze zurück. */
    public final int size() {
        return uiDatasets.size();
    }

    /** Gibt den aktuellen Datensatz zurück. */
    public final Data getActualData() {
        throwExceptionIfEmpty();
        return uiDatasets.get(actualShownIndex);
    }

    /**
     * Gibt den Index des aktuell angezeigten Datensatzes zurück (0-basierend) oder -1, falls die
     * Menge leer ist.
     */
    protected final int getActualShownIndex() {
        throwExceptionIfEmpty();
        return actualShownIndex;
    }

    private void throwExceptionIfEmpty() {
        if (isEmpty()) {
            throw new RuntimeException("Illegale Abfrage auf einer leeren Menge!");
        }
    }

    /** Gibt die Nummer des aktuell angezeigten Datensatzes (1-basierend) zurück. */
    public final int getDocumentNumber() {
        return actualShownIndex + 1;
    }

    /** Legt die Nummer des aktuell angezeigten Datensatzes (1-basierend) fest. */
    public final void setDocumentNumber(int elementNumber) {
        int newActualShownIndex = elementNumber - 1;
        if (newActualShownIndex >= firstIndex() && newActualShownIndex <= lastIndex()) {
            actualShownIndex = newActualShownIndex;
        }
    }

    /** Zeigt den ersten Datensatz an. */
    public final void first() {
        actualShownIndex = firstIndex();
    }

    /** Zeigt den nächsten Datensatz an. */
    public final void next() {
        if (actualShownIndex < lastIndex()) {
            ++actualShownIndex;
        }
    }

    /** Zeigt den vorigen Datensatz an. */
    public final void previous() {
        if (actualShownIndex > firstIndex()) {
            --actualShownIndex;
        }
    }

    /** Zeigt den letzten Datensatz an. */
    public final void last() {
        actualShownIndex = lastIndex();
    }

    /** Gibt an, ob der erste Datensatz angezeigt wird. */
    public final boolean isFirst() {
        return actualShownIndex == firstIndex();
    }

    /** Gibt an, ob der letzte Datensatz angezeigt wird. */
    public final boolean isLast() {
        return actualShownIndex == lastIndex();
    }

    /** Gibt den Index des ersten Datensatzes an (0-basierend). */
    private int firstIndex() {
        return 0;
    }

    /** Gibt den Index des letzten Datensatzes an (0-basierend). */
    private int lastIndex() {
        return size() - 1;
    }

    /** Gibt an, ob die Menge der Daten die navigiert werden, leer ist. */
    public boolean isEmpty() {
        return uiDatasets.isEmpty();
    }

    /** Gibt den Index des übergebenen Datensatzes in der Liste an, -1 falls nicht enthalten. */
    public int indexOf(Data data) {
        return uiDatasets.indexOf(data);
    }

    /** Gibt den Vorgänger zum aktuellen Datensatz zurück, ohne zu diesem weiterzuschalten. */
    public Data getPrevious() {
        throwExceptionIfEmpty();
        if (actualShownIndex > firstIndex()) {
            return uiDatasets.get(actualShownIndex - 1);
        }
        else {
            throw new RuntimeException("Zum ersten Datensatz gibt es keinen Vorgänger.");
        }
    }

    /** Gibt den Nachfolger zum aktuellen Datensatz zurück, ohne zu diesem weiterzuschalten. */
    public Data getNext() {
        throwExceptionIfEmpty();
        if (actualShownIndex < lastIndex()) {
            return uiDatasets.get(actualShownIndex + 1);
        }
        else {
            throw new RuntimeException("Zum letzten Datensatz gibt es keinen Nachfolger.");
        }
    }

}
