/***************************************************************************
                          kmessinterface.cpp  -  description
                             -------------------
    begin                : Sun Dec 29 2002
    copyright            : (C) 2002 by Mike K. Bennett
    email                : mkb137b@hotmail.com
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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 "kmessinterface.h"

#include <qhbox.h>
#include <qlabel.h>
#include <qpoint.h>
#include <qsize.h>
#include <qstringlist.h>

#include <kaction.h>
#include <kconfig.h>
#include <kdebug.h>
#include <kglobal.h>
#include <khelpmenu.h>
#include <kled.h>
#include <klocale.h>
#include <kmenubar.h>
#include <knotifydialog.h>
#include <kpopupmenu.h>
#include <krun.h>
#include <kstatusbar.h>
#include <kstdaction.h>
#include <ktoolbar.h>
#include <kurl.h>

#include "kmessdebug.h"
#include "kmessapplication.h"


// The constructor
KMessInterface::KMessInterface(QWidget *parent, const char *name )
 : KMainWindow(parent,name)
 , connectState_(0)
 , initialized_(false)
{

}



// The destructor
KMessInterface::~KMessInterface()
{
#ifdef KMESSDEBUG_KMESSINTERFACE
  kdDebug() << "DESTROYED KMessInterface " << endl;
#endif
}


// Show the "about KDE" message.
void KMessInterface::aboutKDE()
{
  helpMenu_->aboutKDE();
}



// Show the "about KMess" message.
void KMessInterface::aboutKMess()
{
  helpMenu_->aboutApplication();
}



// "Add a new contact" was selected from the menu.
void KMessInterface::addNewContact()
{
  kdDebug() << "addNewContact not implemented" << endl;
}



// "Add a new group" was selected from the menu.
void KMessInterface::addNewGroup()
{
  kdDebug() << "addNewGroup not implemented" << endl;
}


// The application is closing, after queryExit() was approved
void KMessInterface::applicationClosing()
{
  kdDebug() << "applicationClosing not implemented" << endl;
}


// A status was selected from the menu.
void KMessInterface::changeStatus(const QString& /*statusName*/)
{
  kdDebug() << "changeStatus not implemented" << endl;
}



// A view mode has been selected from the menu.
void KMessInterface::changeViewMode(int /*mode*/)
{
  kdDebug() << "changeViewMode not implemented" << endl;
}


void KMessInterface::showNetworkWindow()
{
  kdDebug() << "showNetworkWindow not implemented" << endl;
}


void KMessInterface::showTransferWindow()
{
  kdDebug() << "showTransferWindow not implemented" << endl;
}



void KMessInterface::configureNotifications()
{
  KNotifyDialog::configure(this);
}



// Create the "Actions" menu
void KMessInterface::createActionsMenu()
{
  KAction         *newAccount, *searchForContact, *searchByInterest, *themes;
  KPopupMenu      *actionsMenu;
  // Create the menu
  actionsMenu = new KPopupMenu( this, "actionsmenu" );

  // Create the "settings" menus
  newAccount       = new KAction( i18n("New &Account"),        "filenew",      0, this, SLOT(           createNewAccount() ), actionCollection(), "newaccount");
  newContact_      = new KAction( i18n("New &Contact"),        "filenew",      0, this, SLOT(              addNewContact() ), actionCollection(), "newcontact");
  newGroup_        = new KAction( i18n("New &Group"),          "filenew",      0, this, SLOT(                addNewGroup() ), actionCollection(), "newgroup");
  configureNotifications_ = KStdAction::configureNotifications(this, SLOT(configureNotifications()), actionCollection());
  settingsActionMenu_ = new KActionMenu( i18n("Account &Settings"), "misc", this, "settings");
  searchForContact = new KAction( i18n("S&earch for Contact"), "find",         0, this, SLOT(           searchForContact() ), actionCollection(), "searchforcontact");
  searchByInterest = new KAction( i18n("Search by &Interest"), "find",         0, this, SLOT( searchForContactByInterest() ), actionCollection(), "searchbyinterest");
  themes = new KAction( i18n("Get New Emoticon or Sound &Themes"), "kmess",    0, this, SLOT(             goToThemesPage() ), actionCollection(), "themes");

  // Plug the items into "settings"
  newContact_             ->plug( actionsMenu );
  newGroup_               ->plug( actionsMenu );
  actionsMenu->insertSeparator();
  searchForContact        ->plug( actionsMenu );
  searchByInterest        ->plug( actionsMenu );
  actionsMenu->insertSeparator();
  newAccount              ->plug( actionsMenu );
  settingsActionMenu_     ->plug( actionsMenu );
  actionsMenu->insertSeparator();
  configureNotifications_ ->plug( actionsMenu );
  themes                  ->plug( actionsMenu );
  // Plug the menu into the menubar
  menuBar()->insertItem( i18n("&Actions"), actionsMenu );
}



// Create the "Connect" menu
void KMessInterface::createConnectMenu()
{
  KAction       *close, *quit;
  KPopupMenu    *connectMenu;
  QStringList    statuses;

  // Create the menu
  connectMenu  = new KPopupMenu( this, "connectmenu" );

  // Create the "connect" menu items
  connectActionMenu_ = new KActionMenu( i18n("Co&nnect"), "connect_creating", this, "connect");
  disconnect_ = new KAction( i18n("&Disconnect"), "connect_no", 0, this, SLOT( disconnectClicked() ), actionCollection(), "disconnect");
  showProfile_ = new KAction( i18n("Show My &Profile"), "kmess", 0, this, SLOT( showUserProfile() ), actionCollection(), "showuserprofile");
  status_ = new KSelectAction( i18n("&My Status"), "misc", 0, this, "status");
  statuses << i18n("Online")
           << i18n("Away")
           << i18n("Away with auto-reply")
           << i18n("Be Right Back")
           << i18n("Busy")
           << i18n("Out to Lunch")
           << i18n("On the Phone")
           << i18n("Invisible");
  status_->setItems(statuses);
  connect ( status_, SIGNAL( activated( const QString& ) ), this, SLOT( changeStatus( const QString& ) ) );
  close = KStdAction::close( this, SLOT( menuClose() ), actionCollection() );
  quit = KStdAction::quit( this, SLOT( menuQuit() ), actionCollection() );

  // Plug the items into "connect"
  connectActionMenu_->plug( connectMenu );
  disconnect_       ->plug( connectMenu );
  disconnect_       ->plug( toolBar("mainToolBar") );
  connectMenu->insertSeparator( );
  status_           ->plug( connectMenu );
  status_           ->plug( toolBar("mainToolBar") );
  showProfile_      ->plug( connectMenu );
  connectMenu->insertSeparator();
  close             ->plug( connectMenu );
  close             ->plug( toolBar("mainToolBar") );
  quit              ->plug( connectMenu );
  quit              ->plug( toolBar("mainToolBar") ); // temp

  // Plug the menu into the menubar
  menuBar()->insertItem( i18n("&Connect"), connectMenu );
}



// Create the "Help" menu
void KMessInterface::createHelpMenu()
{
  KAction       *aboutKDE, *aboutKMess, *helpContents;
  KPopupMenu    *helpMenu;

  // Create the menu
  helpMenu     = new KPopupMenu( this, "helpmenu" );

  // Create the help menu.
  helpMenu_ = new KHelpMenu(this, KGlobal::instance()->aboutData());

  // Create the help menu items
  helpContents = KStdAction::helpContents(this, SLOT( helpContents() ), actionCollection() );
  aboutKMess = KStdAction::aboutApp(this, SLOT( aboutKMess() ), actionCollection() );
  aboutKDE = KStdAction::aboutKDE(this, SLOT( aboutKDE() ), actionCollection() );

  // Plug the items into "help"
  helpContents->plug( helpMenu );
  helpMenu->insertSeparator();
  aboutKMess  ->plug( helpMenu );
  aboutKDE    ->plug( helpMenu );

  // Plug the menu into the menubar
  menuBar()->insertItem( i18n("&Help"), helpMenu );
}



// Create the menus
void KMessInterface::createMenus()
{
  // Create the 4 menus
  createConnectMenu();
  createViewMenu();
  createActionsMenu();
  createHelpMenu();
}



// Create the "View" menu
void KMessInterface::createViewMenu()
{
  QStringList      viewModes;

  // Create the menu
  viewMenu_ = new KPopupMenu( this, "viewmenu" );

  // Create the "view" menu items
  showAllowedAction_ = new KToggleAction( i18n("Show &Allowed Contacts"), 0, KShortcut(), this, "allowed");
  showOfflineAction_ = new KToggleAction( i18n("Show &Offline Contacts"), 0, KShortcut(), this, "offline");
  showRemovedAction_ = new KToggleAction( i18n("Show &Removed Contacts"), 0, KShortcut(), this, "removed");

#ifdef KMESS_NETWORK_WINDOW
  showNetworkAction_ = new KAction(i18n("Show &Network Window"), "bookmark", 0,
                                   this, SLOT(showNetworkWindow()), actionCollection(), "shownetwork");
#endif

  viewMode_ = new KSelectAction( i18n("&Sort Contacts by"), "view_tree", 0, this, "viewmode");
  viewModes << i18n("Group") << i18n("Online/Offline");
  viewMode_->setItems(viewModes);
  connect ( viewMode_, SIGNAL( activated( int ) ), this, SLOT( changeViewMode( int ) ) );

  showTransferAction_ = new KAction(i18n("Show &Transfer Window"), "cache", 0,
                                    this, SLOT(showTransferWindow()), actionCollection(), "showtransfers");

  showToolBar_   = KStdAction::showToolbar  ( this, SLOT( showToolBar() ),   actionCollection() );
  showStatusBar_ = KStdAction::showStatusbar( this, SLOT( showStatusBar() ), actionCollection() );

  // Connect "showAllowed" and "showRemoved"
  connect( showAllowedAction_, SIGNAL( toggled(bool) ), this, SLOT( toggleShowAllowed(bool) ) );
  connect( showOfflineAction_, SIGNAL( toggled(bool) ), this, SLOT( toggleShowOffline(bool) ) );
  connect( showRemovedAction_, SIGNAL( toggled(bool) ), this, SLOT( toggleShowRemoved(bool) ) );

  // Plug the items into "view"
  showAllowedAction_ ->plug( viewMenu_ );
  showRemovedAction_ ->plug( viewMenu_ );
  showOfflineAction_ ->plug( viewMenu_ );
  viewMode_          ->plug( viewMenu_ );
  viewMenu_          ->insertSeparator();
  showTransferAction_->plug( viewMenu_ );
  viewMenu_          ->insertSeparator();
  showToolBar_       ->plug( viewMenu_ );
  showStatusBar_     ->plug( viewMenu_ );

#ifdef KMESS_NETWORK_WINDOW
  viewMenu_->insertSeparator();
  showNetworkAction_->plug( viewMenu_ );
#endif

  // Plug the menu into the menubar
  menuBar()->insertItem( i18n("&View"), viewMenu_ );
}



// "Add new account" has been selected from the menu.
void KMessInterface::createNewAccount()
{
  kdDebug() << "createNewAccount not implemented" << endl;
}



// Disconnect was selected from the menu.
void KMessInterface::disconnectClicked()
{
  kdDebug() << "disconnectClicked not implemented" << endl;
}



// Enable/disable menus based on whether or not the application is
//  connected to the server.
void KMessInterface::enableMenus(bool connected)
{
  connectActionMenu_->setEnabled( !connected );
  disconnect_->setEnabled( connected );
  if ( connected )
  {
    disconnect_->setIcon( "connect_established" );
  }
  else
  {
    disconnect_->setIcon( "connect_no" );
  }
  status_->setEnabled( connected );

  newContact_->       setEnabled( connected );
  newGroup_->         setEnabled( connected );
  showAllowedAction_->setEnabled( connected );
  showOfflineAction_->setEnabled( connected );
  showRemovedAction_->setEnabled( connected );
  showProfile_->      setEnabled( connected );
  viewMode_->         setEnabled( connected );
  // showNetworkAction should ALWAYS be enabled!
}



// Open the kmess themes web page
void KMessInterface::goToThemesPage()
{
  KURL  url( "http://kmess.sourceforge.net/index.php?page=themes" );
  new KRun( url );
}



// Show the user manual for KMess.
void KMessInterface::helpContents()
{
  kapp->invokeHelp("kmess/index");
}



// Initialize the class
bool KMessInterface::initialize()
{
#ifdef KMESSDEBUG_KMESSINTERFACE
  kdDebug() << "KMessInterface - initializing" << endl;
#endif
  if ( initialized_ )
  {
    kdDebug() << "KMessInterface was already initialized." << endl;
    return false;
  }

  // Initialize the status bar
  statusLabel_ = new QLabel( this );
  statusBar()->addWidget( statusLabel_, 2 );

  statusTimer_ = new QLabel( this );
  statusTimer_->setText( "00:00" );
  statusBar()->addWidget( statusTimer_, 0, true );

  statusProgress_ = new KLed( this );
  statusProgress_->setMaximumHeight( 16 );
  statusBar()->addWidget( statusProgress_, 0, true );

  // Create the online timer
  onlineTimer_ = new QTimer( this );
  connect( onlineTimer_,      SIGNAL( timeout()           ),
           this,                SLOT( updateOnlineTimer() ) );

  // Create the menus
  createMenus();

#ifdef KMESSDEBUG_KMESSINTERFACE
  kdDebug() << "KMessInterface - initialized" << endl;
#endif
  return true;
}


// Close has been selected from the menu.
void KMessInterface::menuClose()
{
#ifdef KMESSDEBUG_KMESSINTERFACE
  kdDebug() << "KMessInterface - 'Close' was selected from the menu." << endl;
#endif
  // Hide the window
  hide();
#ifdef KMESSTEST
  ASSERT( isHidden() );
#endif
}



// Quit was selected from the menu.
void KMessInterface::menuQuit()
{
#ifdef KMESSDEBUG_KMESSINTERFACE
  kdDebug() << "KMessInterface - 'Quit' was selected from the menu." << endl;
#endif

  // Tell the application manager we want to quit
  KMessApplication *app = static_cast<KMessApplication *>(kapp);
  app->setQuitSelected(true);

  close();  // Close this window, initiates quit
}



// Reject quitting unless the quit menu was pressed  Called automatically by KMainWindow::closeEvent
bool KMessInterface::queryExit()
{
  return true;
}



// Tell the user that KMess hides in the systray  Called automatically by KMainWindow::closeEvent
bool KMessInterface::queryClose()
{
  // KMessApplication also defines sessionSaving() for KDE 3.1
  KMessApplication *app = static_cast<KMessApplication *>(kapp);

//  if(! app->quitSelected())
//  {
//    // TODO: for KMess 1.5, display that KMess is still visible in the systray.
//    KMessageBox::information( this,
//                              i18n( "Closing the main window will keep KMess running in the "
//                                    "system tray. Use 'Quit' from the 'File' menu to quit the application." ),
//                              i18n( "Docking in System Tray" ), "hideOnCloseInfo" );
//  }



  // Only allow KMess to quit if:
  // - the "quit" option was used from the menu
  // - the session manager wants to quit (we're called from KApplication::commitData())
  if( app->quitSelected() ||
      app->sessionSaving() )
  {
#ifdef KMESSDEBUG_KMESSINTERFACE
    kdDebug() << "KMessInterface::queryClose: Accepting quit request." << endl;
#endif

    // Make sure that substituent also return true
    app->setQuitSelected(true);

    // Make sure some stuff can be cleaned up when leaving kde.
    applicationClosing();
    return true;
  }

#ifdef KMESSDEBUG_KMESSINTERFACE
  kdDebug() << "KMessInterface::queryClose: Rejecting quit request, hiding window" << endl;
#endif

  hide();
  return false;
}



// Restore the window properties (called by KMainWindow)
void KMessInterface::readProperties(KConfig *config)
{
#ifdef KMESSTEST
  ASSERT( config != 0 );
#endif
#ifdef KMESSDEBUG_KMESSINTERFACE
  kdDebug() << "KMessInterface - Reading properties" << endl;
#endif

  // Pull in the window size and position
  config->setGroup("General");
  QSize windowsize = config->readSizeEntry("Size");
  if(!windowsize.isEmpty())
  {
    resize(windowsize);
  }
  QPoint position = config->readPointEntry("Position");
  if(!position.isNull())
  {
    move(position);
  }
  // bar status settings
  bool bViewToolbar = config->readBoolEntry("Show Toolbar", true);
  showToolBar_->setChecked(bViewToolbar);
  showToolBar();

  bool bViewStatusbar = config->readBoolEntry("Show Statusbar", true);
  showStatusBar_->setChecked(bViewStatusbar);
  showStatusBar();

  // bar position settings
  KToolBar::BarPosition toolBarPos;
  toolBarPos=(KToolBar::BarPosition) config->readNumEntry("ToolBarPos", KToolBar::Top);
  toolBar("mainToolBar")->setBarPos(toolBarPos);
#ifdef KMESSDEBUG_KMESSINTERFACE
  kdDebug() << "KMessInterface - Done reading properties" << endl;
#endif


#ifdef KMESSTEST
  ASSERT( config->readSizeEntry("Size") == size() );
  ASSERT( config->readPointEntry("Position") == pos() );
  ASSERT( config->readBoolEntry("Show Toolbar", true) == showToolBar_->isChecked() );
  ASSERT( config->readBoolEntry("Show Statusbar", true) == showStatusBar_->isChecked() );
  ASSERT( config->readNumEntry("ToolBarPos", KToolBar::Top) == (int) toolBar("mainToolBar")->barPos() );
#endif
}


// Save the window properties (called by KMainWindow)
void KMessInterface::saveProperties(KConfig *config)
{
#ifdef KMESSTEST
  ASSERT( config != 0 );
#endif
#ifdef KMESSDEBUG_KMESSINTERFACE
  kdDebug() << "KMessInterface - Saving properties" << endl;
#endif
  config->setGroup("General");
  config->writeEntry("Size",           size()                                 );
  config->writeEntry("Position",       pos()                                  );
  config->writeEntry("Show Toolbar",   showToolBar_->isChecked()              );
  config->writeEntry("Show Statusbar", showStatusBar_->isChecked()            );
  config->writeEntry("ToolBarPos",     (int) toolBar("mainToolBar")->barPos() );
#ifdef KMESSDEBUG_KMESSINTERFACE
  kdDebug() << "KMessInterface - Done saving properties" << endl;
#endif
#ifdef KMESSTEST
  ASSERT( config->readSizeEntry("Size") == size() );
  ASSERT( config->readPointEntry("Position") == pos() );
  ASSERT( config->readBoolEntry("Show Toolbar", true) == showToolBar_->isChecked() );
  ASSERT( config->readBoolEntry("Show Statusbar", true) == showStatusBar_->isChecked() );
  ASSERT( config->readNumEntry("ToolBarPos", KToolBar::Top) == (int) toolBar("mainToolBar")->barPos() );
#endif
}



// Open up the URL for MSN's contact search page.
void KMessInterface::searchForContact()
{
  KURL  url( "http://members.msn.com/find.msnw?pgmarket=en-en" );
  new KRun( url );
}



// Open up the URL to MSN's "search by interest" page.
void KMessInterface::searchForContactByInterest()
{
  KURL  url( "http://members.msn.com/rootcat.msnw?pgmarket=en-en" );
  new KRun( url );
}



// "Show status bar" was toggled.
void KMessInterface::showStatusBar()
{
  if(!showStatusBar_->isChecked())
  {
    statusBar()->hide();
  }
  else
  {
    statusBar()->show();
  }
}



// "Show toolbar" was toggled.
void KMessInterface::showToolBar()
{
  if(!showToolBar_->isChecked())
  {
    toolBar("mainToolBar")->hide();
  }
  else
  {
    toolBar("mainToolBar")->show();
  }
}



// Show the user's MSN profile.
void KMessInterface::showUserProfile()
{
  kdDebug() << "showUserProfile not implemented" << endl;
}



// Change the status bar message.
void KMessInterface::statusMessage( QString message, int connectState )
{
#ifdef KMESSDEBUG_KMESSINTERFACE
  kdDebug() << "STATUS MESSAGE " << message << endl;
#endif
  //statusBar()->clear();
  //statusBar()->changeItem( message, ID_STATUS_MSG );
  statusLabel_->setText( message );

  if ( connectState != connectState_ )
  {
    switch ( connectState )
    {
      case 1:
        statusProgress_->setColor( "#00ff00" );

        onlineTime_ = 0;
        onlineTimer_->start( 60000 );
        break;
      case 2:
        statusProgress_->setColor( "#ffa000" );
        break;
      case 3:
        statusProgress_->setColor( "#ff0000" );

        onlineTimer_->stop();
        statusTimer_->setText( "00:00" );
        break;
    }

    connectState_ = connectState;
  }
}



// The "show allowed contacts" menu item has been toggled.
void KMessInterface::toggleShowAllowed(bool /*show*/)
{
  kdDebug() << "toggleShowAllowed not implemented" << endl;
}



// The "show offline contacts" menu item has been toggled.
void KMessInterface::toggleShowOffline(bool /*show*/)
{
  kdDebug() << "toggleShowOffline not implemented" << endl;
}



// The "show removed contacts" menu item has been toggled.
void KMessInterface::toggleShowRemoved(bool /*show*/)
{
  kdDebug() << "toggleShowRemoved not implemented" << endl;
}


// Increment and update the online timer.
void KMessInterface::updateOnlineTimer()
{
  QString timeText;

  onlineTime_ ++;

  timeText.sprintf( "%02i:%02i", onlineTime_ / 60, onlineTime_ % 60 );

  statusTimer_->setText( timeText );
}

#include "kmessinterface.moc"
