/**********************************************************************
 *
 *   FreeDoko a Doppelkopf-Game
 *    
 *   Copyright (C) 2001-2004  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
 *
 ********************************************************************/


/**
 **
 ** Alpha-Version of FreeDoko 
 **
 **   developed since fall 2001
 **
 **/

#include "constants.h"
#include <time.h>
#ifdef WINDOWS
// for 'mkdir'
#include <io.h>
#else
// for 'mkdir'
#include <sys/stat.h>
#endif

#include "class/getopt/getopt.h"

#include "utils/file.h"
#include "utils/string.h"

#include "utils.h"
#include "basistypes.h"

#include "misc/setting.h"
#include "misc/translator.h"
#include "misc/bug_report.h"

#include "party/party.h"

#include "ui/ui.wrap.h"

#include "os/seed.h"
#include "os/party_points.h"
#include "os/bug_report_replay.h"

UI* ui = NULL;
Translator translator;
Setting setting_default;
Setting setting;
Party party;


#include "player/namegen.h"
#ifndef WINDOWS
int
main(int argc, char* argv[])
#else
  // ToDo: use 'WinMain'
int
main(int argc, char* argv[])
#endif
{
  DEBUG_CALLING(INFO_GAMEPLAY,
		"main()");

  // make an assertion create a bug report
  ::debug_function = &create_assertion_bug_report;

  // initialisation for random functions
  ::srand(static_cast<unsigned>(::time(NULL) % RAND_MAX));

  ui = new UI_Wrap;
#ifndef RELEASE
#ifdef DKNOF
  //static_cast<UI_Wrap*>(ui)->append(new_OS(OS_TYPE::GAMEPLAY));
#endif
#endif

#ifndef RELEASE
  // output of the seed each game
  static_cast<UI_Wrap*>(ui)->append(new OS_NS::Seed(new ofstream((::setting(Setting::PRIVATE_DATA_DIRECTORY) + "/seed").c_str(),
								 ios::app)));
#endif
#ifndef RELEASE
  // output of the party points
  static_cast<UI_Wrap*>(ui)->append(new OS_NS::PartyPoints(new ofstream("FreeDoko.party_points")));
#endif

  // set the default ui
#if defined(USE_UI_GTKMM)
  UI* ui_tmp = new_UI(UI_TYPE::GTKMM_DOKO);
#elif defined(USE_UI_AATEXT)
  UI* ui_tmp = new_UI(UI_TYPE::AATEXT);
#elif defined(USE_UI_TEXT)
  UI* ui_tmp = new_UI(UI_TYPE::TEXT);
#else
  UI* ui_tmp = new_UI(UI_TYPE::NONE);
#endif
  { // parse options

    // This file contains the help you get calling the program with '-?'.
    // It includes what arguments you can use.
#ifdef WINDOWS
#include "text/gpl.dos.string"
#include "text/help.dos.string"
#else
#include "text/gpl.string"
#include "text/help.string"
#endif

    // load the settings
    setting.load();
    if (FAST_PLAY)
      ::setting.set(Setting::SAVE_PARTY_CHANGES, false);

    // parse the options
    GetOpt::Option option;
    while (option =
	   GetOpt::getopt(argc, argv,
			  "help", '?', GetOpt::Syntax::BOOL,
			  "hilfe", 'h', GetOpt::Syntax::BOOL,
			  "version", 'v', GetOpt::Syntax::BOOL,
			  "license", 'L', GetOpt::Syntax::BOOL,
			  "ui", 'u', GetOpt::Syntax::BSTRING,
			  "settings", 's', GetOpt::Syntax::BSTRING,
			  "name", 'n', GetOpt::Syntax::BSTRING,
			  "language", 'l', GetOpt::Syntax::BSTRING,
			  "cardset", 'C', GetOpt::Syntax::BSTRING,
			  "cards_height", 'H', GetOpt::Syntax::UNSIGNED,
			  "bug_report", 'b', GetOpt::Syntax::BSTRING,
#ifndef RELEASE
			  "fast_play", 'F', GetOpt::Syntax::BOOL,
#endif
			  // end of arguments
			  "", 0, GetOpt::Syntax::END)) {

      if (option.fail()
	  || (option.name() == "")) {
	if (option.name() == "")
	  option.error_v = GetOpt::Option::FALSE_ARGUMENT;
	// wrong usage
	cerr << argv[0] << "\n"
	  << "wrong usage: "
	  << option.error() << " " << option.value_string() << "\n"
	  << "For the syntax type '" << argv[0] << " -?'"
	  << endl;

	DEBUG_RETURNING(1,
			INFO_GAMEPLAY,
			"main()");
      } // if (option.fail())

      if ((option.name() == "help") 
	  || (option.name() == "hilfe")) {
	// output of the help
	cout << help_string << endl;
	DEBUG_RETURNING(0,
			INFO_GAMEPLAY,
			"main()");
      } else if (option.name() == "version") {
	// output of the version
	cout << "FreeDoko " << VERSION << "\n"
	  << "\n"
	  << GPL_string;
	DEBUG_RETURNING(0,
			INFO_GAMEPLAY,
			"main()");
      } else if (option.name() == "license") {
	// output of the license (GPL)
	cout << "FreeDoko -- License:\n\n"
	  << GPL
	  << '\n'
	  << '\n'
	  << "----------\n"
	  << '\n'
	  << "Cardset '" << ::setting(Setting::CARDSET) << "' license:\n"
	  << cardset_license
	  << endl;
	DEBUG_RETURNING(0,
			INFO_GAMEPLAY,
			"main()");
      } else if (option.name() == "ui") {
	delete ui_tmp;
	if (option.value_string() == "none")
	  ui_tmp = new_UI(UI_TYPE::NONE);
#ifdef USE_UI_TEXT
	else if (option.value_string() == "text")
	  ui_tmp = new_UI(UI_TYPE::TEXT);
#endif
#ifdef USE_UI_GTKMM
	else if (option.value_string() == "gtkmm")
	  ui_tmp = new_UI(UI_TYPE::GTKMM_DOKO);
#endif
	else {
	  cerr << "ui '" << option.value_string() << "' not implemented.\n"
	    << "exiting";
	  return 1;
	} // if (option.value_string() == "...")
      } else if (option.name() == "settings") {
	setting.load(option.value_string());
      } else if (option.name() == "name") {
	setting.set(Setting::NAME, option.value_string());
      } else if (option.name() == "language") {
	setting.set(Setting::LANGUAGE, option.value_string());
      } else if (option.name() == "graphic_size") {
	setting.set(Setting::CARDS_HEIGHT,
		    option.value(GetOpt::Option::UNSIGNED));
      } else if (option.name() == "cardset") {
	setting.set(Setting::CARDSET, option.value_string());
      } else if (option.name() == "bug_report") {
	static_cast<UI_Wrap*>(::ui)->append(new (OS_NS::BugReportReplay)(option.value_string()));
#ifndef RELEASE
      } else if (option.name() == "fast_play") {
	FAST_PLAY = option.value(GetOpt::Option::BOOL);
	::setting.set(Setting::SAVE_PARTY_CHANGES, false);
	// change all humans to ai's
	for (unsigned p = 0; p < ::party.playerno(); p++)
	  if (::party.player(p).type() == Player::HUMAN)
	    ::party.playertype_set(p, Player::AI);
#endif
      } else {
	cerr << "Option " << option.name() << " unknown!" << endl;
	exit(1);
      } // if (option.name() == ...)
    } // while (getopt())
  } // parse options

  { // set the ui
    static_cast<UI_Wrap*>(::ui)->ui = ui_tmp;

    if (SEED_OUT) {
      delete static_cast<UI_Wrap*>(::ui)->ui;
      static_cast<UI_Wrap*>(::ui)->ui = new UI(UI_TYPE::NONE);
    } // if (SEED_OUT)

    // test, whether the ui is valid
    if ((::ui->type() == UI_TYPE::NONE)
	&& !FAST_PLAY) {
      cerr << "Uitype is 'none', aborting." << endl;
#ifdef RELEASE
      exit(1);
#endif
    } // if (::ui->type() == UI::NONE)
  } // set the ui

  { // if this is the first start, create some directories
    vector<string> dirnames;
    dirnames.push_back(::setting(Setting::PRIVATE_DATA_DIRECTORY));
    dirnames.push_back(::setting(Setting::PRIVATE_DATA_DIRECTORY)
		       + "/" + ::setting(Setting::RULES_DIRECTORY));
    dirnames.push_back(::setting(Setting::PRIVATE_DATA_DIRECTORY)
		       + "/" + ::setting(Setting::AI_DIRECTORY));
    Translator::Translation information = ::translator("");
    
      for (vector<string>::iterator dir = dirnames.begin();
	   dir != dirnames.end();
	   dir++) {
	if (!DK::Utils::File::isdirectory(*dir)) {
	  information += (::translator("creating directory \'%sdir%\'",
				       *dir)
			  + "\n");
#ifdef WINDOWS
	  mkdir(dir->c_str());
#else
	  mkdir(dir->c_str(), 00700);
#endif
	} // if (!isdirectory(*dir))
      } // for (dir \in dirnames)
      if (!information.empty())
	::ui->information(information);
  } // if this is the first start, create some directories

  { // read the version of the last usage of FreeDoko and write the new version

    // read the old version
    DK::Utils::Version* const version_old
      = DK::Utils::new_Version_from_file(::setting(Setting::PRIVATE_DATA_DIRECTORY)
					 + "/Version");

    { // write the new version
      ofstream ostr((::setting(Setting::PRIVATE_DATA_DIRECTORY)
		     + "/Version").c_str());
      if (!ostr.fail())
	ostr << version;
    } // write the new version

    if (version_old == NULL) {
      // This seems to be the first start -- give some introduction.
      ::ui->information(::translator("_first run_"));
    } else { // if !(version_old == NULL)
      // Compare the old version with the new version and give some output.
      if (*version_old < version)
	::ui->information(::translator("_Version " + version.number_to_string()
				       + "_"));
#ifndef OUTDATED
      if (*version_old < DK::Utils::Version(0, 6, 3)) {
	::ui->information(::translator("_Adjusting settings time_"));
	// adjust the times in the settings
	::setting.set(Setting::CARD_PLAY_DELAY,
		      100 * ::setting(Setting::CARD_PLAY_DELAY));
	::setting.set(Setting::CARD_INVALID_DELAY,
		      100 * ::setting(Setting::CARD_INVALID_DELAY));
	::setting.set(Setting::FULL_TRICK_CLOSE_DELAY,
		      100 * ::setting(Setting::FULL_TRICK_CLOSE_DELAY) );
	::setting.set(Setting::GAMETYPE_WINDOW_CLOSE_DELAY,
		      100 * ::setting(Setting::GAMETYPE_WINDOW_CLOSE_DELAY));
	::setting.set(Setting::MARRIAGE_WINDOW_CLOSE_DELAY,
		      100 * ::setting(Setting::MARRIAGE_WINDOW_CLOSE_DELAY));
	::setting.set(Setting::GENSCHER_WINDOW_CLOSE_DELAY,
		      100 * ::setting(Setting::GENSCHER_WINDOW_CLOSE_DELAY));
	::setting.set(Setting::ANNOUNCEMENT_WINDOW_CLOSE_DELAY,
		      100 * ::setting(Setting::ANNOUNCEMENT_WINDOW_CLOSE_DELAY));
	::setting.set(Setting::SWINES_WINDOW_CLOSE_DELAY,
		      100 * ::setting(Setting::SWINES_WINDOW_CLOSE_DELAY));
      } // if !(version_old == NULL)
#endif

      delete version_old;
    } // if (version_old != NULL)

  } // read the version of the last usage of FreeDoko and write the new version

  // at the bug report in the ui.wrap,
  // so it gets the information of the gameplay
  static_cast<UI_Wrap*>(::ui)->append(&::bug_report);


  // init the ui
  ::ui->init(argc = 1, argv);


  // load the default rules from the private data directory
  ::party.rule().load(::setting(Setting::PRIVATE_DATA_DIRECTORY)
		      + "/"
		      + ::setting(Setting::RULES_DIRECTORY)
		      + "/last");

  // now the preparatinos have finished

  while (game_status != GAMESTATUS::QUIT) {
    ::ui->party_open();
    // start playing
    ::game_status = GAMESTATUS::PARTY_PLAY;
    ::party.play();
    ::ui->party_close();
  } // while (game_status != QUIT)

  // when exiting save the settings (once again)
  ::setting.save();

  // clean up
  delete ::ui;

  DEBUG_RETURNING(0,
		  INFO_GAMEPLAY,
		  "main()");
} // int main(argc, argv)
