/******************************************************************************
 ** $Id: Eigenschaften.java 844 2016-01-01 16:56:22Z 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;

import jafuffy.bedienung.Oberflaeche;
import jafuffy.logik.Beginner;
import jafuffy.logik.Spieler;
import jafuffy.logik.Variante;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;

/**
 * Umfasst Programm- und Turniereigenschaften; inklusive erstmalige Pfadeinstellung.
 */
@SuppressWarnings("serial")
public final class Eigenschaften extends Properties {

    /** Die globalen Eigenschaften für ganz JaFuffy. */
    public static final Eigenschaften GLOBAL;

    /** Hinweiszeile in der Einstellungsdatei. */
    private static final String HINWEIS = "JaFuffy-Einstellungen (bitte nicht von Hand ändern)";
    /** Name der Einstellungsdatei. */
    private static final String INI = "JaFuffy.ini";

    /** Voreinstellungen der Eigenschaften. */
    private static final Vorbelegung VORBELEGUNG = new Vorbelegung(Ressource.soundsystem());

    static {
        SecurityManager sicherheit = System.getSecurityManager();
        Eigenschaften global;
        if (sicherheit == null) {
            String pfad = System.getProperty("user.home") + File.separator + INI;
            global = new Eigenschaften(new File(pfad));
        } else {
            try {
                sicherheit.checkPropertyAccess("user.home");
                String pfad = System.getProperty("user.home") + File.separator + INI;
                sicherheit.checkRead(pfad);
                sicherheit.checkWrite(pfad);
                global = new Eigenschaften(new File(pfad));
            } catch (SecurityException e) {
                global = new Eigenschaften();
            }
        }
        GLOBAL = global;
    }

    /**
     * Wandelt Aktivstatus in String um.
     *
     * @param aktiv
     *            Gibt an, ob Eigenschaft aktiv ist.
     * @return Aktivstatus als String.
     */
    static String status(boolean aktiv) {
        return aktiv ? "aktiv" : "passiv";
    }

    /** Einstellungsdatei. */
    private File datei;

    /** Applet-Konstruktor. */
    private Eigenschaften() {
        super(VORBELEGUNG);
    }

    /**
     * Konstruktor für Applikation.
     *
     * @param datei
     *            Eigenschaftendatei
     */
    private Eigenschaften(File datei) {
        super(VORBELEGUNG);
        if (datei.exists()) {
            try {
                FileInputStream reader = new FileInputStream(datei);
                // Auslesen der Einstellungsdatei
                load(reader);
                reader.close();
            } catch (IOException exeption) {
                exeption.printStackTrace();
            }
        }
        // Merken der Einstellungdatei
        this.datei = datei;
    }

    /**
     * Zustand eines Schlüssels erfragen.
     *
     * @param schluessel
     *            Schlüssel der Eigenschaft.
     * @return Gibt an, ob der Wert des Schlüssels aktiv ist.
     */
    public boolean aktiv(String schluessel) {
        return getProperty(schluessel).equals("aktiv");
    }

    /**
     * @return Index des Beginnmodus.
     * @see Beginner
     */
    public int beginnmodus() {
        return Beginner.valueOf(getProperty("Beginnmodus")).ordinal();
    }

    /**
     * Liefert ein File-Objekt zum Dateinamen zurück, zusammengebaut aus dem Speicherverzeichnis und dem Dateinamen.
     *
     * @param name
     *            Der Dateiname, aus dem das File-Objekt erzeugt wird.
     *
     * @return Das File-Objekt zur Datei.
     */
    public File datei(String name) {
        return new File(getProperty("Pfad"), name);
    }

    /**
     * Erststart erfragen.
     *
     * @return Gibt an, ob Erststart erfolgt ist.
     */
    public boolean erststart() {
        return getProperty("Starts").equals("0");
    }

    /**
     * @return Gibt an ob im vohergehenden Programmlauf ein Neustart angefordert wurde, allerdings kein Turnier am
     *         laufen war.
     */
    public boolean kaltstart() {
        return getProperty("Neustart").equals("kalt");
    }

    /**
     * Merkt in den Einstellungen, ob ein Neustart angefordert wurde.
     *
     * @param warm
     *            Ein Turnier ist am laufen.
     */
    public void merkeNeustartAnforderung(boolean warm) {
        setProperty("Neustart", warm ? "warm" : "kalt");
    }

    /** @return Gibt an ob im vohergehenden Programmlauf ein Neustart angefordert wurde. */
    public boolean neustart() {
        return kaltstart() || warmstart();
    }

    /** @return Pfad zum Speicherort der Statistik und den Turnierständen. */
    public String pfad() {
        return getProperty("Pfad");
    }

    /**
     * Setzt den Pfad zum Speicherort der Statistik und den Turnierständen.
     *
     * @param pfad
     *            Der zu setzende Pfad.
     */
    public void pfad(String pfad) {
        setProperty("Pfad", pfad);
    }

    /**
     * Ein Neustart wurde durchgeführt, braucht also beim nächsten Programmstart nicht mehr berücksichtigt werden.
     */
    public void quittiereNeustartAnforderung() {
        setProperty("Neustart", "passiv");
    }

    /**
     * Speichern der Eigenschaften in Datei.
     *
     * @param x
     *            X-Koordinate der linken oberen Ecke des Programmfensters.
     * @param y
     *            Y-Koordinate der linken oberen Ecke des Programmfensters.
     * @param b
     *            Breite des Programmfensters.
     * @param h
     *            Höhe des Programmfensters.
     * @throws IOException
     *             Geworfen, falls Einstellungen nicht gespeichert werden können.
     */
    public void speichere(int x, int y, int b, int h) throws IOException {
        setProperty("X", String.valueOf(x));
        setProperty("Y", String.valueOf(y));
        setProperty("Breite", String.valueOf(b));
        setProperty("Hoehe", String.valueOf(h));
        setProperty("Starts", String.valueOf(Integer.parseInt(getProperty("Starts")) + 1));
        FileOutputStream writer = new FileOutputStream(datei);
        store(writer, HINWEIS);
        writer.close();
    }

    /**
     * @return Index der Spielregelvariante.
     * @see Variante
     */
    public int variante() {
        return Variante.valueOf(getProperty("Variante")).ordinal();
    }

    /**
     * @return Gibt an ob im vohergehenden Programmlauf ein Neustart angefordert wurde, allerdings ein Turnier am laufen
     *         war.
     */
    public boolean warmstart() {
        return getProperty("Neustart").equals("warm");
    }

    /**
     * Eigenschaften umschalten (aktiv <-> passiv).
     *
     * @param schluessel
     *            Der Schlüssel, dessen boolescher Wert gewechselt werden soll.
     */
    public void wechsle(String schluessel) {
        setProperty(schluessel, status(!aktiv(schluessel)));
    }
}

/** Die Voreinstellungen für die Eigenschaften. */
@SuppressWarnings("serial")
class Vorbelegung extends Properties {

    /**
     * Nimmt die Voreinstellungen vor.
     *
     * @param soundsystem
     *            Gibt an, ob ein Soundsystem vorhanden ist.
     */
    public Vorbelegung(boolean soundsystem) {
        setProperty("Geraeusche", Eigenschaften.status(soundsystem));
        setProperty("LookAndFeel", Oberflaeche.standardLookAndFeel());
        setProperty("Variante", Variante.KLASSISCH.name());
        setProperty("Beginnmodus", Beginner.VERLIERER.name());
        setProperty("Anzahl", "0");
        setProperty("Einfachklick", "passiv");
        setProperty("Hinweis", "aktiv");
        setProperty("Spicker", "aktiv");
        setProperty("Erinnerung", "aktiv");
        setProperty("Intro", "aktiv");
        setProperty("Geraeusche", "aktiv");
        setProperty("X", "0");
        setProperty("Y", "0");
        setProperty("Breite", "640");
        setProperty("Hoehe", "480");
        setProperty("Nachschauen", "passiv");
        setProperty("Starts", "0");
        setProperty("Zwischenstand", "passiv");
        setProperty("Neustart", "passiv");
        setProperty("Pfad", System.getProperty("user.home"));
        for (int i = 0; i < Spieler.SPIELER; i++) {
            setProperty("Spieler" + i, "");
            setProperty("Bot" + i, "passiv");
        }
        setProperty("Ueberlegungsdarstellungsbeschleunigung", "aktiv");
        setProperty("Aktionsdarstellungsbeschleunigung", "passiv");
    }
}
