/******************************************************************************
 ** $Id: Auswertung.java 665 2015-01-10 17:10:26Z 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 2 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, write to the Free Software
 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 ******************************************************************************
 ** 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;

import java.lang.reflect.Constructor;

/**
 * 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".
 */
abstract class Auswertung extends Aenderungen<CEAblauf> {

    private static final long serialVersionUID = -7315969783651586016L;

    static Constructor<? extends Auswertung> auswertungskonstruktor(
            Class<? extends Auswertung> klasse) {
        try {
            return klasse.getConstructor(Variante.class, Wuerfel[].class);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /** Tipps (=Prognose) berechnen? */
    private boolean tipps;
    /** Im Turnier benutzte Würfel. */
    final Wuerfel[] wuerfel;
    /** Enthält Auswertungs- und Prognosedaten. */
    Analyse analyse;
    /** Aktiver Spieler. */
    Spieler spieler;

    /** Spielvariante */
    final Variante variante;

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

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

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

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

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

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

    /** @return Bestmöglicher Eintrag zum Setzen ausgewählt? */
    boolean bester(Tabzeile eintrag) {
        return analyse.bester() == eintrag;
    }

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

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

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

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

    /**
     * @param eintrag
     *            noch nicht gesetzter Eintrag
     * @return Tipp, wie viele Punkte für aktiven Spieler erreichbar
     */
    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
     *            Nummer des Eintrags auf dem Punktezettel
     * @return Wichtung (Qualität der erreichbaren Punktzahl)
     */
    float wichtung(Tabzeile eintrag) {
        return analyse.wichtung(eintrag);
    }

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

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

}
