/******************************************************************************
 ** $Id: Bestenliste.java 826 2015-11-29 22:56:05Z 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.bedienung;

import jafuffy.logik.BestenlisteModell;
import jafuffy.logik.CEJaFuffy;
import jafuffy.logik.CEStatistik;
import jafuffy.logik.Statistik;
import jafuffy.logik.Variante;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.FontMetrics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.text.NumberFormat;

import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;
import javax.swing.border.EtchedBorder;
import javax.swing.border.MatteBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

/**
 * Anzeige der Bestenlisten (Name, Datum, Punktzahl, Kommentar), aufgeschlüsselt nach
 * Spielvarianten. Gleiche Punktzahl bedeutet gleicher Rang. Gezeigt werden die ersten 10 Ränge.
 */
@SuppressWarnings("serial")
public class Bestenliste extends JDialog implements PropertyChangeListener, ChangeListener {

    // Icon für Rahmen
    private static final ImageIcon MEDAILLE = Grafik.icon("Goldwuerfel.png");
    // Spaltenzwischenraum
    private static final int ZWISCHENRAUM = 4;

    // Spaltenindizierung
    enum Spalten {
        RANG, NAME, PUNKTE, DATUM, KOMMENTAR
    };

    // statistische Datenfelder
    private final JLabel[] anzahl = new JLabel[Variante.values().length];
    private final JLabel[] durchschnitt = new JLabel[Variante.values().length];
    private final JLabel[] standardabweichung = new JLabel[Variante.values().length];
    // Karteikarten für Bestenlisten (nach Spielregeln aufgeschlüsselt)
    private final JTabbedPane tabbedPane = new JTabbedPane();
    // Modelle für die einzelnen Karteikarten
    private final BestenlisteModell[] bestenlisteModelle;
    private final Statistik statistik;

    /**
     * Konstruktor.
     *
     * @param statistik
     *            Daten für die Bestenlisten
     * @param variante
     *            Spielvariante bei Programmstart
     */
    public Bestenliste(Statistik statistik, int variante) {

        this.statistik = statistik;
        UIManager.addPropertyChangeListener(this);

        // Vorbereitung
        JPanel pane = new JPanel(new BorderLayout(8, 8));
        pane.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
        bestenlisteModelle = statistik.bestenlisteModelle();
        for (Variante var : Variante.values()) {
            int i = var.ordinal();
            // statistische Kenndaten
            JPanel statistikfelder = new JPanel(new FlowLayout(FlowLayout.CENTER, 8, 4));
            statistikfelder.add(anzahl[i] = new JLabel());
            anzahl[i].setToolTipText("Anzahl aller bisherigen Spiele (" + var.toString() + ")");
            statistikfelder.add(durchschnitt[i] = new JLabel());
            durchschnitt[i].setToolTipText("Punktedurchschnitt aller bisherigen Spiele ("
                    + var.toString() + ")");
            statistikfelder.add(standardabweichung[i] = new JLabel());
            standardabweichung[i].setToolTipText("Standardabweichung für bisherige Spiele ("
                    + var.toString() + ")");
            // Bestenliste
            JTable table = new JTable(bestenlisteModelle[i]);
            table.setIntercellSpacing(new Dimension(ZWISCHENRAUM, 0));
            table.getColumnModel().getColumn(Spalten.RANG.ordinal())
                    .setPreferredWidth(spaltenbreite("Rang"));
            table.getColumnModel().getColumn(Spalten.NAME.ordinal())
                    .setPreferredWidth(spaltenbreite("!Mitspieler!"));
            table.getColumnModel().getColumn(Spalten.PUNKTE.ordinal())
                    .setPreferredWidth(spaltenbreite("Punkte"));
            table.getColumnModel().getColumn(Spalten.DATUM.ordinal())
                    .setPreferredWidth(spaltenbreite("00.00.0000"));
            table.getColumnModel().getColumn(Spalten.KOMMENTAR.ordinal())
                    .setMinWidth(spaltenbreite("Ein Spielerkommentar."));
            table.setRowSelectionAllowed(false);
            // Kenndaten+Bestenliste zusammenbauen, einfügen als Karteikarte
            JScrollPane scrollPane = new JScrollPane(table);
            scrollPane.setBorder(BorderFactory.createCompoundBorder(new MatteBorder(MEDAILLE),
                    new EtchedBorder(EtchedBorder.LOWERED)));
            scrollPane.setPreferredSize(new Dimension(16 * MEDAILLE.getIconWidth(),
                    8 * MEDAILLE.getIconWidth()));
            JPanel daten = new JPanel(new BorderLayout());
            daten.add(statistikfelder, BorderLayout.NORTH);
            daten.add(scrollPane, BorderLayout.CENTER);
            daten.setBorder(new EmptyBorder(0, 4, 8, 4));
            tabbedPane.addTab(var.toString(), daten);
        }
        tabbedPane.setSelectedIndex(variante);
        JButton ok = new JButton("OK");
        ok.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                setVisible(false);
            }
        });

        // Aufbau
        pane.add(tabbedPane, BorderLayout.CENTER);
        pane.add(ok, BorderLayout.SOUTH);
        belegeFelder();
        getRootPane().setDefaultButton(ok);
        setContentPane(pane);
        setTitle("JaFuffy (Liste der zehn besten Punktzahlen)");
        setIconImages(Oberflaeche.LOGOS);
        pack();

    }

    /**
     * Realisiert Veränderungen des Look&Feel.
     *
     * @param evt
     */
    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        if (evt.getPropertyName().equals("lookAndFeel")) {
            SwingUtilities.updateComponentTreeUI(this);
        }
    }

    /**
     * Modelldaten habe sich geändert.
     *
     * @param ce
     */
    @Override
    public void stateChanged(ChangeEvent ce) {
        if (CEJaFuffy.adressiert(ce, CEStatistik.class)) {
            CEJaFuffy<CEStatistik> cej = CEJaFuffy.ereignisbehaelter(ce);
            switch (cej.ereignis()) {
            case TURNIER_START:
            case TURNIER_WEITER:
                tabbedPane.setSelectedIndex(statistik.variante());
                break;
            case SPIEL_ENDE:
                bestenlisteModelle[statistik.variante()].aktualisieren();
                tabbedPane.setSelectedIndex(statistik.variante());
                belegeFelder();
                break;
            default:
                break;
            }
        }
    }

    // Ausgabefelder für statistische Daten belegen
    private void belegeFelder() {
        for (Variante var : Variante.values()) {
            int i = var.ordinal();
            anzahl[i].setText("Anzahl: " + statistik.n(i));
            if (statistik.n(i) > 1) {
                durchschnitt[i].setText("Durchschnitt: "
                        + NumberFormat.getInstance().format(
                                Math.floor(statistik.durchschnitt(i) * 10. + 0.5) / 10.));
                standardabweichung[i].setText("Standardabweichung: "
                        + NumberFormat.getInstance().format(
                                Math.floor(statistik.standardabweichung(i) * 10. + 0.5) / 10.));
            } else {
                durchschnitt[i].setText("Durchschnitt: -");
                standardabweichung[i].setText("Standardabweichung: -");
            }
        }
    }

    /**
     * Berechnet überschlagsweise Spaltenbreite
     *
     * @titel titel Spaltentitel
     */
    private int spaltenbreite(String titel) {
        FontMetrics metrik = getFontMetrics(getFont());
        int breite = metrik.stringWidth(titel);
        return breite;
    }

}
