/******************************************************************************
 ** $Id: Wuerfel.java 739 2015-05-23 16:13:32Z 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 java.util.Random;

import javax.swing.JToggleButton;
import javax.swing.event.ChangeListener;

/** Würfelmodell. */
public class Wuerfel extends JToggleButton.ToggleButtonModel implements Comparable<Wuerfel> {

    /** Zur Serialisierung. */
    private static final long serialVersionUID = 6889772262239748227L;

    /** Zufallsgenerator. */
    private static final Random ZUFALL = new Random();

    /** Die Anzahl aller möglichen Augen. */
    public static final int AUGEN = 6;

    /** Änderungen im Zustand. */
    private final Aenderungen<CEWuerfel> aenderungen;
    /** Augenzahl (von eins bis sechs). */
    private int augen;
    /** Würfel zum erneuten Würfeln vorschlagen? */
    private boolean vorgeschlagen;

    /**
     * Konstruktor.
     *
     * @param augen
     *            Ursprüngliche Augenzahl
     */
    Wuerfel(int augen) {
        this.augen = augen;
        aenderungen = new Aenderungen<CEWuerfel>();
    }

    /**
     * ChangeListener hinzufügen.
     *
     * @param changeListener
     *            Objekt, das auf Änderungsereignisse reagiert.
     */
    public void installiereChangeListener(ChangeListener changeListener) {
        aenderungen.addChangeListener(changeListener);
    }

    /**
     * @return -1,0,+1 (Vergleich)
     */
    @Override
    public int compareTo(Wuerfel wuerfel) {
        if (augen() < wuerfel.augen()) {
            return -1;
        }
        if (augen() > wuerfel.augen()) {
            return +1;
        }
        return 0;
    }

    /**
     * ChangeListener entfernen.
     *
     * @param changeListener
     *            Zuvor registriertes Beobachtungsobjekt.
     */
    public void entferneChangeListener(ChangeListener changeListener) {
        aenderungen.removeChangeListener(changeListener);
    }

    /**
     * Würfelauswahl mit Geräuscheffekten.
     *
     * @param selektiert
     *            Gibt an, ob der Würfel ausgewählt und damit in den Becher gelegt werden soll.
     */
    @Override
    public void setSelected(boolean selektiert) {
        boolean feuern = isSelected() ^ selektiert;
        super.setSelected(selektiert);
        if (feuern) {
            aenderungen.fireStateChanged(selektiert ? CEWuerfel.ANWAHL : CEWuerfel.ABWAHL);
        }
    }

    /**
     * @return Augenzahl von eins bis sechs
     */
    public int augen() {
        return augen;
    }

    /**
     * Würfel zum erneuten Werfen vorschlagen.
     *
     * @param vorschlagen
     *            Gibt an, ob der Würfel zum erneuten Werfen vorgeschlagen ist.
     */
    void setzeVorschlag(boolean vorschlagen) {
        vorgeschlagen = vorschlagen;
    }

    /** @return Zum erneuten Würfeln vorgeschlagen? */
    public boolean vorgeschlagen() {
        return vorgeschlagen;
    }

    /** Würfel werfen. Ein anstehender Vorschlag wird dann zurückgenommen. */
    void wirf() {
        vorgeschlagen = false;
        augen = ZUFALL.nextInt(AUGEN) + 1;
        aenderungen.fireStateChanged(CEWuerfel.WURF); // muss vor Abwahl erfolgen
        setSelected(false);
    }

}
