/******************************************************************************
 ** $Id: Auswertung.java 741 2015-05-26 20:51:29Z wmh $
 ** Diese Datei ist Bestandteil der Java-Quelltexte des Würfelspiels JaFuffy.
 ** Lauffähig ab Java 6.
 ******************************************************************************
 ** Copyright (C) Wolfgang Hauck <wolfgang.hauck@3kelvin.de>
 ******************************************************************************
 ** This program is free software: you can redistribute it and/or modify
 ** it under the terms of the GNU General Public License as published by
 ** the Free Software Foundation, either version 3 of the License, or
 ** (at your option) any later version.
 **
 ** This program is distributed in the hope that it will be useful,
 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 ** GNU General Public License for more details.
 **
 ** You should have received a copy of the GNU General Public License
 ** along with this program.  If not, see <http://www.gnu.org/licenses/>.
 ******************************************************************************
 ** Die aktuellste Version von JaFuffy findet sich im Internet unter
 ** <http://jafuffy.3kelvin.de>.
 **
 ** Kommentare, Fehler oder Erweiterungswünsche bitte per E-Mail senden an
 ** <jafuffy@3kelvin.de>.
 ******************************************************************************/
package jafuffy.logik;

import jafuffy.Eigenschaften;

/**
 * Auswertung des Wurfs. Textnachrichten. Hinweise zur erwürfelten Punktzahl. Setztipps. Bei der
 * Serialisation brauchen nicht alle Daten gespeichert zu werden, diese werden rekonstruiert
 * durch Funktionsaufruf von "gewuerfelt".
 */
public abstract class Auswertung extends Aenderungen<CEAblauf> {

    /** Ermöglicht Serialisierung. */
    private static final long serialVersionUID = -7315969783651586016L;

    /** Im Turnier benutzte Würfel. */
    protected final Wuerfel[] wuerfel;
    /** Enthält Auswertungs- und Prognosedaten. */
    protected final Analyse analyse;

    /** Tipps (=Prognose) berechnen? */
    protected boolean tipps;
    /** Aktiver Spieler. */
    protected Spieler spieler;

    /**
     * Konstruktor.
     *
     * @param wuerfel
     *            Die im Turnier benutzten Würfel.
     */
    Auswertung(Wuerfel[] wuerfel) {
        this.wuerfel = wuerfel;
        analyse = new Analyse(wuerfel);
    }

    /**
     * @return Die Tabellenzeile des besten Eintrages; -1 falls keiner vorhanden ist.
     */
    public Tabzeile bester() {
        return analyse.bester();
    }

    /**
     * @param eintrag
     *            Die Eintragszeile in der Tabelle.
     * @return Bestmöglicher Eintrag zum Setzen ausgewählt?
     */
    public boolean bester(Tabzeile eintrag) {
        return analyse.bester() == eintrag;
    }

    /**
     * @param eintrag
     *            Noch nicht gesetzter Eintrag.
     * @return Tipp, wie viele Punkte für aktiven Spieler erreichbar sind.
     */
    public String spicker(Tabzeile eintrag) {
        String text;
        if (Eigenschaften.GLOBAL.aktiv("Spicker") && spieler.gewuerfelt()
                && spieler.setzbar(eintrag) && eintrag.alle()) {
            int punkte = wert(eintrag);
            text = new Integer(punkte).toString() + (punkte != 1 ? " Punkte" : " Punkt");
            if (tipps()) {
                text =
                        "<html>" + "<p>" + text + "</p>"
                                + "<p><small><i>Siehe auch Kontextmenü!</i></small></p>"
                                + "<p><small><i>Beachte Menü \"Extras\".</i></small></p>"
                                + "</html>";
            }
        } else {
            text = null;
        }
        return text;
    }

    /**
     * @param eintrag
     *            Zeilennummer des Eintrags
     * @return Texteintrag in Tabelle (für aktiven Spieler)
     */
    public abstract String text(Tabzeile eintrag);

    /** @return Stehen Tipps zur Verfügung? */
    public boolean tipps() {
        return tipps;
    }

    /**
     * @return Auswertungsname
     */
    @Override
    public abstract String toString();

    /**
     * @param eintrag
     *            Eintrag
     * @return Entspricht die Würfelauswahl dem Vorschlag?
     */
    public boolean vorgeschlagen(Tabzeile eintrag) {
        return analyse.vorgeschlagen(eintrag);
    }

    /**
     * Einen Auswahlvorschlag der Würfel erstellen (nach Würfeln), für bestimmten Eintrag.
     *
     * @param eintrag
     *            Eintrag
     */
    public void vorschlagen(Tabzeile eintrag) {
        for (int w = 0; w < Turnier.WUERFEL; w++) {
            wuerfel[w].setzeVorschlag(analyse.erneut(eintrag, w));
        }
        fireStateChanged(CEAblauf.VORSCHLAGEN);
    }

    /**
     * @param eintrag
     *            Nummer des Eintrags auf dem Punktezettel
     * @return erwürfelte Punkte des aktiven Spielers für das Eintragsfeld
     */
    public abstract int wert(Tabzeile eintrag);

    /**
     * @param eintrag
     *            Nummer des Eintrags auf dem Punktezettel
     * @return Wichtung (Qualität der erreichbaren Punktzahl)
     */
    public float wichtung(Tabzeile eintrag) {
        return analyse.wichtung(eintrag);
    }

    /** @return geschätzte Abweichung von mittlerer Punktzahl pro Spiel */
    abstract int abweichung();

    /**
     * @param spieler
     *            Spieler, der gewürfelt hat.
     */
    void gewuerfelt(Spieler spieler) {
        this.spieler = spieler;
        tipps = false;
        analyse.errechne();
    }

    /** @return geschätzte mittlere Punktzahl pro Spiel */
    abstract int mittelwert();

    /**
     * @param tipps
     *            Tipps/Prognosen geben?
     */
    void tipps(boolean tipps) {
        if (tipps) {
            if (!this.tipps) {
                analyse.prognostiziere(spieler);
                this.tipps = true;
            }
        } else {
            this.tipps = false;
        }
    }

    /**
     * Den besten Auswahlvorschlag der Würfel erstellen (nach Würfeln).
     *
     * @param Eintrag
     */
    void vorschlagen() {
        tipps(true);
        vorschlagen(bester());
    }

}
