/**********************************************************************
 *
 *   FreeDoko a Doppelkopf-Game
 *    
 *   Copyright (C) 2001-2006  by Diether Knof and Borg Enders
 *
 *   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 can find this license in the file 'gpl.txt'.
 *
 *   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
 *
 *  Contact:
 *    Diether Knof dknof@gmx.de
 *    Borg Enders  borg@borgsoft.de
 *
 *********************************************************************/

#ifndef CLASS_SETTING_HEADER
#define CLASS_SETTING_HEADER

#include "../basistypes.h"

#include "setting.cardsorder.h"
#include "translator.h"

/**
 **
 ** the class for all preferences
 **
 ** @author	Diether Knof
 **
 **/
class Setting {
  public:
    enum TypeBool {
      FIRST,
      BOOL_FIRST = FIRST,

      SAVE_PARTY_CHANGES = BOOL_FIRST,
      SHOW_SPLASH_SCREEN,
      SPLASH_SCREEN_TRANSPARENT,
      SHOW_BUG_REPORT_BUTTON_IN_GAME_FINISHED_WINDOW,
      SAVE_BUG_REPORTS_ON_DESKTOP,
      SOUND,

      AUTOMATIC_CARD_SUGGESTION,
      ANNOUNCE_SWINES_AUTOMATICALLY,

      SHOW_IF_VALID,
      EMPHASIZE_VALID_CARDS,
      ANNOUNCE_IN_TABLE,
      SHOW_ALL_HANDS,
      SHOW_AI_INFORMATION_HANDS,
      SHOW_AI_INFORMATION_TEAMS,
      SHOW_TRICKPILES_POINTS,
      SHOW_KNOWN_TEAMS_IN_GAME,
      SHOW_SOLOPLAYER_IN_GAME,

      SHOW_FULL_TRICK_WINDOW,
      SHOW_FULL_TRICK_WINDOW_IF_SPECIAL_POINTS,
      CLOSE_FULL_TRICK_AUTOMATICALLY,

      SHOW_GAMETYPE_WINDOW,
      CLOSE_GAMETYPE_WINDOW_AUTOMATICALLY,
      SHOW_MARRIAGE_WINDOW,
      CLOSE_MARRIAGE_WINDOW_AUTOMATICALLY,
      SHOW_GENSCHER_WINDOW,
      CLOSE_GENSCHER_WINDOW_AUTOMATICALLY,
      SHOW_ANNOUNCEMENT_WINDOW,
      CLOSE_ANNOUNCEMENT_WINDOW_AUTOMATICALLY,
      SHOW_SWINES_WINDOW,
      CLOSE_SWINES_WINDOW_AUTOMATICALLY,

      NETWORK_CONNECTIONS_URGENCY_HINT,
      NETWORK_CHAT_URGENCY_HINT,

      ROTATE_TRICK_CARDS,

      OWN_HAND_ON_TABLE_BOTTOM,

      ORIGINAL_CARDS_SIZE,

      BOOL_LAST = ORIGINAL_CARDS_SIZE
    }; // enum TypeBool
    static unsigned const BOOL_NUMBER;

    enum TypeUnsigned {
      UNSIGNED_FIRST = BOOL_LAST + 1,

      CARD_PLAY_DELAY = UNSIGNED_FIRST,
      FULL_TRICK_CLOSE_DELAY,

      GAMETYPE_WINDOW_CLOSE_DELAY,
      MARRIAGE_WINDOW_CLOSE_DELAY,
      GENSCHER_WINDOW_CLOSE_DELAY,
      ANNOUNCEMENT_WINDOW_CLOSE_DELAY,
      SWINES_WINDOW_CLOSE_DELAY,

      TABLE_ROTATION,

      CARDS_HEIGHT,

      UNSIGNED_LAST = CARDS_HEIGHT
    }; // enum TypeUnsigned
    static unsigned const UNSIGNED_NUMBER;

    enum TypeString {
      STRING_FIRST = UNSIGNED_LAST + 1,

      NAME = STRING_FIRST,
      LANGUAGE,
      CARDSET,
      CARDS_BACK,
      BACKGROUND,
      NAME_FONT,
      NAME_FONT_COLOR,
      NAME_ACTIVE_FONT_COLOR,
      TRICKPILE_POINTS_FONT,
      TRICKPILE_POINTS_FONT_COLOR,
      POVERTY_SHIFT_ARROW_COLOR,

      BROWSER,

      STRING_LAST = BROWSER
    }; // enum TypeString
    static unsigned const STRING_NUMBER;

    enum TypeStringConst {
      STRING_CONST_FIRST = STRING_LAST + 1,

      PUBLIC_DATA_DIRECTORY = STRING_CONST_FIRST,
      PRIVATE_DATA_DIRECTORY,
      SETTINGS_FILE,
      LANGUAGES_DIRECTORY,
      LANGUAGE_FILE,
      GRAPHIC_EXTENSION,
      CARDSETS_DIRECTORY,
      CARDS_DIRECTORY,
      CARDS_BACK_DIRECTORY,
      ICONS_DIRECTORY,
      BACKGROUNDS_DIRECTORY,
      SOUND_DIRECTORY,
      AI_DIRECTORY,
      PARTIES_DIRECTORY,
      RULES_DIRECTORY,
      SETTINGS_DIRECTORY,
      MANUAL_DIRECTORY,

      STRING_CONST_LAST = MANUAL_DIRECTORY
    }; // enum TypeStringConst
    static unsigned const STRING_CONST_NUMBER;

    enum TypeCardsOrder {
      CARDS_ORDER = STRING_CONST_LAST + 1,

      LAST = CARDS_ORDER
    }; // enum TypeCardsOrder

  public:
    Setting();
    Setting(Setting const& setting);
    Setting& operator=(Setting const& setting);

    vector<string> data_directories() const;

    // returns, whether the setting is activ or not (or the value)
    bool operator()(const TypeBool type) const;
    unsigned operator()(const TypeUnsigned type) const;
    string operator()(const TypeString type) const;
    string operator()(const TypeStringConst type) const;
    CardsOrder const& operator()(const TypeCardsOrder type) const;
    CardsOrder& operator()(const TypeCardsOrder type);

    // returns the type with the name
    int type(string const& name) const;
    // returns the type with the translated name
    int type_translated(string const& name) const;
    // returns the type with the translated or normal name
    int type_translated_or_normal(string const& name) const;
    
    // returns, whether the dependencies of the settings are met
    bool dependencies(TypeBool const& type) const;
    bool dependencies(TypeUnsigned const& type) const;
    bool dependencies(TypeString const& type) const;

    // returns the setting
    bool const& value(TypeBool const type) const;
    unsigned const& value(TypeUnsigned const type) const;
    string const& value(TypeString const type) const;
    string const value(TypeStringConst const type) const;
    CardsOrder const& value(TypeCardsOrder const type) const;
    CardsOrder& value(TypeCardsOrder const type);

    // the minimum and maximum value
    unsigned min(TypeUnsigned const& type) const;
    unsigned max(TypeUnsigned const& type) const;

    // sets the setting
    bool set(string const& type, string const& value);
    bool set(const TypeBool type, bool const value);
    bool set(const TypeBool type, string const& value);
    string set(const TypeString type, string const& value);
    unsigned set(const TypeUnsigned type, unsigned const value);
    unsigned set(const TypeUnsigned type, string const& value);
    CardsOrder const& set(const TypeCardsOrder type,
			  CardsOrder const& value);
    CardsOrder const& set(const TypeCardsOrder type,
			  string const& value);

    void update_all();

    void load();
    void load(string const& filename,
		  bool filename_not_exists_output = true);

    bool save() const;
    bool save(string const& filename) const;

    // write of the settings
    ostream& write(ostream& ostr) const;

  private:
    vector<bool> bool_p;
    vector<unsigned> unsigned_p;
    vector<string> string_p;
    CardsOrder cards_order_p;

}; // class Setting

// conversion in a string
string name(Setting::TypeBool const& type);
string name(Setting::TypeUnsigned const& type);
string name(Setting::TypeString const& type);
string name(Setting::TypeStringConst const& type);
string name(Setting::TypeCardsOrder const& type);

// local macro
#define WRITE_NAME(Type) \
  inline ostream& operator<<(ostream& ostr, Type const& t) \
  { return (ostr << ::name(t)); }

// output of the names
WRITE_NAME(Setting::TypeBool)
WRITE_NAME(Setting::TypeUnsigned)
WRITE_NAME(Setting::TypeString)
WRITE_NAME(Setting::TypeStringConst)
WRITE_NAME(Setting::TypeCardsOrder)
#undef WRITE_NAME

// output of the Settings
ostream& operator<<(ostream& ostr, Setting const& setting);

// comparison of two settings (value)
bool operator==(Setting const& setting1, Setting const& setting2);
bool operator!=(Setting const& setting1, Setting const& setting2);

extern Setting setting;
extern Setting setting_default;

extern string GPL;
extern string cardset_license;

inline
Translator::Translation translation(Setting::TypeBool const& type)
{ return Translator::Translation(::translator,
				 "Setting::"
				 + ::name(type)); }
inline
Translator::Translation translation(Setting::TypeUnsigned const& type)
{ return Translator::Translation(::translator,
				 "Setting::"
				 + ::name(type)); }
inline
Translator::Translation translation(Setting::TypeString const& type)
{ return Translator::Translation(::translator,
				 "Setting::"
				 + ::name(type)); }
inline
Translator::Translation translation(Setting::TypeStringConst const& type)
{ return Translator::Translation(::translator,
				 "Setting::"
				 + ::name(type)); }
inline
Translator::Translation translation(Setting::TypeCardsOrder const& type)
{ return Translator::Translation(::translator,
				 "Setting::"
				 + ::name(type)); }

#endif // #ifndef CLASS_SETTING_HEADER
