/***************************************************************************
                          tdepacman.cpp  -  description
                             -------------------
    begin                : Sam Jan 19 13:37:57 CET 2002
    copyright            : (C) 1998-2003 by Jörg Thönnissen
    email                : joe@dsite.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 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

// include files for TQt
#include <tqkeycode.h>
#include <tqcolor.h>
#include <tqstring.h>
#include <tqmsgbox.h>

// include files for TDE
#include <kcolordlg.h>
#include <kstatusbar.h>
#include <kstdaction.h>
#include <kstdgameaction.h>

// application specific includes
#include "tdepacman.h"

#define ID_STATUS_MSG 1

TDEpacmanApp::TDEpacmanApp(TQWidget *, const char *name) : TDEMainWindow(0, name)
{
  config=kapp->config();

  ///////////////////////////////////////////////////////////////////
  // call inits to invoke all other construction parts
  initStatusBar();
  initActions();
  initView();
	
  readOptions();

  highscoresChecked = false;
  focusedPause = false;

  connect(view->referee, SIGNAL(setScore(int, int)), view->score, SLOT(setScore(int, int)));
  connect(view->referee, SIGNAL(setPoints(int)), view->score, SLOT(set(int)));
  connect(view->referee, SIGNAL(setLifes(int)), view->status, SLOT(setLifes(int)));
  connect(view->referee, SIGNAL(setLevel(int)), view->status, SLOT(setLevel(int)));

  connect(view->referee, SIGNAL(focusedGamePause()), this, SLOT(slotFocusedGamePause()));
  connect(view->referee, SIGNAL(forcedGameHighscores()), this, SLOT(slotForcedGameHighscores()));

  connect(view->score, SIGNAL(gameHighscores()), this, SLOT(slotGameHighscores()));
  connect(view->score, SIGNAL(gameFinished()), this, SLOT(slotGameFinished()));
}

TDEpacmanApp::~TDEpacmanApp()
{

}


void TDEpacmanApp::initActions()
{
  gameNew = KStdGameAction::gameNew(this, SLOT(slotGameNew()), actionCollection());
  gamePause = KStdGameAction::pause(this, SLOT(slotGamePause()), actionCollection());
  gamePause->setAccel(Key_F3);
  gameQuit = KStdGameAction::quit(this, SLOT(slotGameQuit()), actionCollection());
  gameHighscores = KStdGameAction::highscores(this, SLOT(slotGameHighscores()), actionCollection());
  showMenuBar = KStdAction::showMenubar(this, SLOT(slotShowMenuBar()), actionCollection());
  showToolBar = KStdAction::showToolbar(this, SLOT(slotShowToolBar()), actionCollection());
  showStatusBar = KStdAction::showStatusbar(this, SLOT(slotShowStatusBar()), actionCollection());
  showMouseCursor = new TDEToggleAction(i18n("Show Mouse&cursor"), 0,
                                      this, SLOT(slotShowMouseCursor()), actionCollection(),
                                      "options_show_mousecursor");
  selectGraphicScheme = new TDEActionMenu(i18n("&Select graphic scheme"), actionCollection(),
  						                          "options_select_graphic_scheme");
  KStdAction::keyBindings(this, SLOT(slotKeyBindings()), actionCollection());
  focusOutPause = new TDEToggleAction(i18n("Pause in &Background"), 0,
                                    this, SLOT(slotFocusOutPause()), actionCollection(),
                                    "options_focus_out_pause");
  focusInContinue = new TDEToggleAction(i18n("Continue in &Foreground"), 0,
                                      this, SLOT(slotFocusInContinue()), actionCollection(),
                                      "options_focus_in_continue");

  showMenuBar->setStatusText(i18n("Enables/disables the menubar"));
  showToolBar->setStatusText(i18n("Enables/disables the toolbar"));
  showStatusBar->setStatusText(i18n("Enables/disables the statusbar"));
  showMouseCursor->setStatusText(i18n("Enable/disables the mousecursor"));

  // use the absolute path to your tdepacmanui.rc file for testing purpose in createGUI();
  createGUI();
}


void TDEpacmanApp::initStatusBar()
{
  ///////////////////////////////////////////////////////////////////
  // STATUSBAR
  // TODO: add your own items you need for displaying current application status.
  statusBar()->insertItem(i18n("Ready."), ID_STATUS_MSG);
}

void TDEpacmanApp::initView()
{
  ////////////////////////////////////////////////////////////////////
  // create the main widget here that is managed by TDEMainWindow's view-region and
  // connect the widget.

  view = new TDEpacmanView(this);
  setCentralWidget(view);	

  setFixedSize(view->width(), view->height());
  view->referee->setFocus();
}

void TDEpacmanApp::saveOptions()
{	
  // config->setGroup("General Options");
  config->writeEntry("Geometry", size());
  config->writeEntry("ShowMenubar", showMenuBar->isChecked());
  config->writeEntry("ShowToolbar", showToolBar->isChecked());
  config->writeEntry("ShowStatusbar", showStatusBar->isChecked());
  config->writeEntry("ShowMousecursor", showMouseCursor->isChecked());
  config->writeEntry("FocusOutPause", focusOutPause->isChecked());
  config->writeEntry("FocusInContinue", focusInContinue->isChecked());
  config->writeEntry("ToolBarPos", (int) toolBar("mainToolBar")->barPos());
  config->writeEntry("Scheme", scheme);
  config->writeEntry("Mode", mode);
}

void TDEpacmanApp::readOptions()
{
	
  // config->setGroup("General Options");

  // bar status settings
  bool bShowMenubar = config->readBoolEntry("ShowMenubar", true);
  showMenuBar->setChecked(bShowMenubar);
  slotShowMenuBar();

  bool bShowToolbar = config->readBoolEntry("ShowToolbar", true);
  showToolBar->setChecked(bShowToolbar);
  slotShowToolBar();

  bool bShowStatusbar = config->readBoolEntry("ShowStatusbar", false);
  showStatusBar->setChecked(bShowStatusbar);
  slotShowStatusBar();

  // cursor status settings
  bool bShowMousecursor = config->readBoolEntry("ShowMousecursor", false);
  showMouseCursor->setChecked(bShowMousecursor);
  slotShowMouseCursor();

  // focus status settings
  bool bFocusOutPause = config->readBoolEntry("FocusOutPause", false);
  focusOutPause->setChecked(bFocusOutPause);
  slotFocusOutPause();

  bool bFocusInContinue = config->readBoolEntry("FocusInContinue", false);
  focusInContinue->setChecked(bFocusInContinue);
  slotFocusInContinue();

  // bar position settings
  TDEToolBar::BarPosition toolBarPos;
  toolBarPos = (TDEToolBar::BarPosition) config->readNumEntry("ToolBarPos", TDEToolBar::Top);
  toolBar("mainToolBar")->setBarPos(toolBarPos);
	
  TQSize size = config->readSizeEntry("Geometry");
  if (!size.isEmpty())
  {
    resize(size);
  }

  // scheme and mode
  scheme = config->readNumEntry("Scheme", -1);
  mode = config->readNumEntry("Mode", -1);
  readSchemes();
}

void TDEpacmanApp::readSchemes()
{
  TQString saveGroup = config->group();
  TQString group;
  TQString description;

  int modeCount = config->readNumEntry("ModeCount", -1);
  int schemeCount = config->readNumEntry("SchemeCount");

  modeID.resize(modeCount > 0 ? modeCount : 0);
  schemeID.resize(schemeCount);
  schemeMode.resize(schemeCount);

  schemesPopup = new TQPtrList<TDEPopupMenu>;
  schemesPopup->setAutoDelete(true);

  modesPopup = selectGraphicScheme->popupMenu();
  connect(modesPopup, SIGNAL(activated(int)), this, SLOT(slotSchemeActivated(int)));

  if (schemeCount == 0 || scheme == -1) {
    TQMessageBox::warning(this, i18n("Configuration Error"),
                               i18n("There are no schemes defined,\n"
                                    "or no scheme is selected."));
    return;
  }

  // create submenus (TQPopupMenu) for graphic-modes
  for (int m = 0; m < modeCount; m++) {
    group.sprintf("Mode %d", m);
    config->setGroup(group);

    description = config->readEntry("Description", group);

    TDEPopupMenu *p = new TDEPopupMenu;
    p->setCheckable(true);
    connect(p, SIGNAL(activated(int)), this, SLOT(slotSchemeActivated(int)));
    schemesPopup->append(p);

    modeID[m] = modesPopup->insertItem(description, schemesPopup->at(m));
    modesPopup->setItemEnabled(modeID[m], false);
    modesPopup->setItemChecked(modeID[m], m == mode);
  }

  // create menuitems (insertItem) for graphic-schemes
  for (int i = 0; i < schemeCount; i++) {
    group.sprintf("Scheme %d", i);
    config->setGroup(group);

    description = config->readEntry("Description", group);
    schemeMode[i] = config->readNumEntry("Mode", -1);

    if (schemeMode[i] == -1) {
      schemeID[i] = modesPopup->insertItem(description);
      modesPopup->setItemChecked(schemeID[i], i == scheme);
    } else {
      schemeID[i] = schemesPopup->at(schemeMode[i])->insertItem(description);
      schemesPopup->at(schemeMode[i])->setItemChecked(schemeID[i], i == scheme);
      modesPopup->setItemEnabled(modeID[schemeMode[i]], true);
    }
  }

  config->setGroup(saveGroup);
}

bool TDEpacmanApp::queryExit()
{
  saveOptions();
  return true;
}


/////////////////////////////////////////////////////////////////////
// SLOT IMPLEMENTATION
/////////////////////////////////////////////////////////////////////

void TDEpacmanApp::slotGameNew()
{
  // enable the gameHighscores action, if disabled by forced highscores mode
  if (!gameHighscores->isEnabled())
    gameHighscores->setEnabled(true);

  // hide highscores and show board again, if in highscores mode
  if (highscoresChecked)
    slotGameHighscores();

  // deactivate pause and uncheck the menuitem, if in pause state
  if (gamePause->isChecked()) {
    gamePause->setChecked(false);
    slotGamePause();
  }
  // disable menuitem to prevent interruption of the game
  gameNew->setEnabled(false);

  view->referee->play();
}

void TDEpacmanApp::slotGamePause()
{
  view->referee->pause();
  view->score->setPause(gamePause->isChecked());
}

void TDEpacmanApp::slotFocusedGamePause()
{
  // if an focus-event triggers the pause, toggle the gamePause checked
  gamePause->setChecked(!gamePause->isChecked());
  focusedPause = !focusedPause;

  slotGamePause();
}

void TDEpacmanApp::slotGameHighscores()
{
  // toggle highscores mode flag
  highscoresChecked = !highscoresChecked;

  view->referee->toggleHallOfFame();

  // show highscore (by lowering referee and status) or return to play (by raising them again)
  if (highscoresChecked) {
    view->referee->lower();
    view->status->lower();
  } else {
    view->status->raise();
    view->referee->raise();
    view->referee->setFocus();

    // after forced highscores comes the intro again
    if (!gameHighscores->isEnabled()) {
      gameHighscores->setEnabled(true);
      view->referee->intro();
    }
  }
}

void TDEpacmanApp::slotForcedGameHighscores()
{
    // disable menuitem to prevent closing highscores display
    gameHighscores->setEnabled(false);

    slotGameHighscores();
}

void TDEpacmanApp::slotGameQuit()
{
  slotStatusMsg(i18n("Exiting..."));
  saveOptions();
  kapp->quit();
}

void TDEpacmanApp::slotShowMenuBar()
{
  slotStatusMsg(i18n("Toggling menubar..."));
  ///////////////////////////////////////////////////////////////////
  // turn Menubar on or off
  if(!showMenuBar->isChecked()) {
    menuBar()->hide();
    setFixedSize(view->width(), view->height());
  } else {
    menuBar()->show();
  }		

  slotStatusMsg(i18n("Ready."));
}

void TDEpacmanApp::slotShowToolBar()
{
  slotStatusMsg(i18n("Toggling toolbar..."));
  ///////////////////////////////////////////////////////////////////
  // turn Toolbar on or off
  if(!showToolBar->isChecked()) {
    toolBar("mainToolBar")->hide();
    setFixedSize(view->width(), view->height());
  } else {
    toolBar("mainToolBar")->show();
  }		

  slotStatusMsg(i18n("Ready."));
}

void TDEpacmanApp::slotShowStatusBar()
{
  slotStatusMsg(i18n("Toggle the statusbar..."));
  ///////////////////////////////////////////////////////////////////
  // turn Statusbar on or off
  if(!showStatusBar->isChecked()) {
    statusBar()->hide();
    setFixedSize(view->width(), view->height());
  } else {
    statusBar()->show();
  }

  slotStatusMsg(i18n("Ready."));
}

void TDEpacmanApp::slotShowMouseCursor()
{
  slotStatusMsg(i18n("Toggle the mousecursor..."));
  ///////////////////////////////////////////////////////////////////
  // turn Mousecursor on or off
  if(!showMouseCursor->isChecked()) {
    view->setCursor(blankCursor);
  } else {
    view->setCursor(arrowCursor);
  }

  slotStatusMsg(i18n("Ready."));
}

void TDEpacmanApp::slotSchemeActivated(int id)
{
  slotStatusMsg(i18n("Graphic scheme selected..."));
  ///////////////////////////////////////////////////////////////////
  // select activated scheme/mode

  mode = -1;
  scheme = -1;

  for (uint s = 0; s < schemeID.size(); s++) {
    if (schemeID[s] == id) {
      scheme = s;
      mode = schemeMode[s];
    }
    if (schemeMode[s] == -1) {
  		modesPopup->setItemChecked(schemeID[s], schemeID[s] == id);
		} else {
			modesPopup->setItemChecked(modeID[schemeMode[s]], schemeMode[s] == mode);
			schemesPopup->at(schemeMode[s])->setItemChecked(schemeID[s], schemeID[s] == id);
	  }
	}

  view->setScheme(scheme, mode);
  setFixedSize(view->width(), view->height());

  slotStatusMsg(i18n("Ready."));
}

void TDEpacmanApp::slotFocusOutPause()
{
  slotStatusMsg(i18n("Toggle focusOutPause..."));
  ///////////////////////////////////////////////////////////////////
  // turn focusOutPause on or off
  view->referee->setFocusOutPause(focusOutPause->isChecked());

  slotStatusMsg(i18n("Ready."));
}

void TDEpacmanApp::slotFocusInContinue()
{
  slotStatusMsg(i18n("Toggle focusInContinue..."));
  ///////////////////////////////////////////////////////////////////
  // turn focusInContinue on or off
  view->referee->setFocusInContinue(focusInContinue->isChecked());

  slotStatusMsg(i18n("Ready."));
}

void TDEpacmanApp::slotKeyBindings()
{
  slotStatusMsg(i18n("Configure key bindings..."));
  ///////////////////////////////////////////////////////////////////
  // configure key bindings
  PKeys *keys = new PKeys();
  if (keys->exec() == TQDialog::Accepted) {
    view->referee->initKeys();
    view->score->initKeys();
  }
  delete keys;

  slotStatusMsg(i18n("Ready."));
}

void TDEpacmanApp::slotGameFinished()
{
  slotStatusMsg(i18n("Game finished..."));
  ///////////////////////////////////////////////////////////////////
  // enable/disable the menuitem
  gameNew->setEnabled(true);

  slotStatusMsg(i18n("Ready."));
}

void TDEpacmanApp::slotStatusMsg(const TQString &text)
{
  ///////////////////////////////////////////////////////////////////
  // change status message permanently
  statusBar()->clear();
  statusBar()->changeItem(text, ID_STATUS_MSG);
}

#include "tdepacman.moc"
