/***************************************************************************
                          contactstatus.cpp
                             -------------------
    begin                : Sunday March 9th 2008
    copyright            : (C) 2008 by Richard Conway
    email                : richardconway1984 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 "msnstatus.h"

#include "../kmessdebug.h"

#include <KAction>
#include <KIconEffect>
#include <KIconLoader>
#include <KLocale>
#include <KMenu>


// Initialize the status menu
KMenu* MsnStatus::statusMenu_( 0 );

MsnStatus::~MsnStatus()
{
  delete statusMenu_;
}

/**
 * Returns an icon for the specified status
 *
 * Additionally, you can specify a flag you want to overlay on the status icon.
 *
 * @param status Status for which to create the picture
 * @param flags  Optional flags to add overlays, @see Flags enum
 * @return The status icon
 */
QPixmap MsnStatus::getIcon( const Status status, const Flags flags )
{
  QString iconBase;
  // initially set the overlay icon to an empty string as we do not know
  // at this point if we want one.
  QString iconOverlay;

  // Set the base icon depending on the status
  switch( status )
  {
    case STATUS_ONLINE:        iconBase = "user-online";         break;
    case STATUS_BUSY:          iconBase = "user-busy";           break;
    case STATUS_AWAY:          iconBase = "user-away";           break;
    case STATUS_IDLE:          iconBase = "user-away-extended";  break;
    case STATUS_INVISIBLE:     iconBase = "user-invisible";      break;
    case STATUS_OFFLINE:       iconBase = "user-offline";        break;

    case STATUS_BE_RIGHT_BACK:
      iconBase    = "user-away";
      iconOverlay = "contact_away_overlay";
      break;

    case STATUS_AWAY_AUTOREPLY:
      iconBase    = "user-away";
      iconOverlay = "contact_invisible_overlay";
      break;

    case STATUS_ON_THE_PHONE:
      iconBase    = "user-away-extended";
      iconOverlay = "contact_phone_overlay";
      break;

    case STATUS_OUT_TO_LUNCH:
      iconBase    = "user-away-extended";
      iconOverlay = "contact_food_overlay";
      break;

    default:
      kmWarning() << "Invalid status" << status << "!";
  }

  // Choose the picture's overlay, if any.
  // FIXME: there is no 'blocked' image or overlay image in the oxygen icon set
  // One may be released in time, for now use the busy overlay as it looks the part
  // in the CURRENT oxygen theme! this may change
  switch( flags )
  {
    case FlagNone:          break;
    case FlagBlocked:       iconOverlay = "contact_busy_overlay"; break;
    case FlagWebMessenger:  break;
    case FlagMobile:        break;
  }

  // Load the icon
  QPixmap icon = KIconLoader::global()->loadIcon( iconBase, KIconLoader::Small );

  // Add the overlay if needed
  if( ! iconOverlay.isEmpty() )
  {
    // Add the overlay image to our icon
    QPixmap overlayIcon  = KIconLoader::global()->loadIcon( iconOverlay, KIconLoader::Small );
    QImage  iconImage    = icon.toImage();
    QImage  overlayImage = overlayIcon.toImage();

    KIconEffect::overlay( iconImage, overlayImage );
    icon = QPixmap::fromImage( iconImage );
  }

  return icon;
}



/**
 * Returns the icon name for the specified status
 *
 * Only the base icon name can be returned.
 *
 * @param status        KMess::MsnStatus for which to create the picture
 * @return The status icon
 */
QString MsnStatus::getIconName( const Status status )
{
  // Set the base icon depending on the status
  switch( status )
  {
    case STATUS_ONLINE:        return "user-online";
    case STATUS_BUSY:          return "user-busy";
    case STATUS_BE_RIGHT_BACK:
    case STATUS_AWAY:          return "user-away";
    case STATUS_ON_THE_PHONE:
    case STATUS_OUT_TO_LUNCH:
    case STATUS_IDLE:          return "user-away-extended";
    case STATUS_INVISIBLE:     return "user-invisible";
    case STATUS_OFFLINE:       return "user-offline";

    default:
      kmWarning() << "Invalid status" << status << "!";
  }

  return "user-online";
}



/**
 * Returns a three-letter code (like BSY for Busy) for a status
 *
 * @param status The status to convert
 * @return Three-letter status code
 */
QString MsnStatus::getCode( const Status status )
{
  // Just return the code
  switch( status )
  {
    case STATUS_ONLINE:         return QString( "NLN" );
    case STATUS_AWAY:           return QString( "AWY" );
    case STATUS_AWAY_AUTOREPLY: return QString( "AWY" );
    case STATUS_BE_RIGHT_BACK:  return QString( "BRB" );
    case STATUS_BUSY:           return QString( "BSY" );
    case STATUS_INVISIBLE:      return QString( "HDN" );
    case STATUS_IDLE:           return QString( "IDL" );
    case STATUS_OFFLINE:        return QString( "FLN" );
    case STATUS_ON_THE_PHONE:   return QString( "PHN" );
    case STATUS_OUT_TO_LUNCH:   return QString( "LUN" );
    default:
      kmWarning() << "Invalid status" << status << "!";
      return QString( "NLN" );
  }
}



/**
 * Returns the localized name for a status
 *
 * @param status The status to convert
 * @return Localized status name
 */
QString MsnStatus::getName( const Status status )
{
  // Localize and return the status name
  switch( status )
  {
    case STATUS_ONLINE:         return i18n( "Online"               );
    case STATUS_BUSY:           return i18n( "Busy"                 );
    case STATUS_AWAY:           return i18n( "Away"                 );
    case STATUS_AWAY_AUTOREPLY: return i18n( "Away with Auto-Reply" );
    case STATUS_IDLE:           return i18n( "Idle"                 );
    case STATUS_BE_RIGHT_BACK:  return i18n( "Be Right Back"        );
    case STATUS_ON_THE_PHONE:   return i18n( "On the Phone"         );
    case STATUS_OUT_TO_LUNCH:   return i18n( "Out to Lunch"         );
    case STATUS_INVISIBLE:      return i18n( "Invisible"            );
    case STATUS_OFFLINE:        return i18n( "Offline"              );

    default:
      kmWarning() << "Invalid status" << status << "!";
      return i18n( "Online" );
  }
}



/**
 * Create and return a menu with all the states
 *
 * It also has a Disconnect option (instead of Offline)
 * Be sure to actually attach the returned menu to some toolbar or the like,
 * or it won't be properly deleted.
 *
 * @return KMenu with a QAction for each available Status
 */
KMenu *MsnStatus::getStatusMenu()
{
  if( statusMenu_ != 0 )
  {
    return statusMenu_;
  }

  statusMenu_ = new KMenu();
  statusMenu_->addTitle( KIcon( "go-jump" ), i18n( "&My Status" ) );
  statusMenu_->setIcon( KIcon( "go-jump" ) );
  statusMenu_->setTitle( i18n( "&My Status" ) );
  Status status;
  KAction *action;

  // This loop assumes that a) STATES_NUMBER is the last item of the Status enum, and
  // b) STATUS_OFFLINE is the second last. Fun stuff happens if it is not the case.
  for( int index = 0; index < STATES_NUMBER; ++index )
  {
    // Setting the action's data allows us to later retrieve the
    // Status from a triggered QAction
    status = (Status) index;
    action = new KAction( KIcon( getIcon( status ) ), getName( status ), statusMenu_ );
    action->setData( status );

    // The disconnection action is a bit special :)
    if( status == STATUS_OFFLINE )
    {
      // Divide the normal states from the disconnection action
      statusMenu_->addSeparator();

      // Change its name: "Offline" is misleading.
      action->setText( i18nc( "Menu action name", "Disconnect" ) );
    }

    statusMenu_->addAction( action );
  }

  /* TODO: After the AccountCurrentAccount rewrite, move the MsnStatus menu's signal connection
           from class KMessInterface::initialize() to here, with something like:
             connect( status_,        SIGNAL(    triggered(QAction*) ),
                     currentAccount_, SLOT  ( changeStatus(QAction*) ) );
           To avoid adding such a stupid slot on CurrentAccount, it'd be better to add it
           somewhere else (here?) to get the Status out of the QAction.
  */

  return statusMenu_;
}



/**
 * Convert a three-letter code to a status
 *
 * @param status The status to convert
 * @return MSN Status enum value
 */
Status MsnStatus::codeToStatus( const QString &status )
{
       if( status == "AWY" ) return STATUS_AWAY;
  else if( status == "BRB" ) return STATUS_BE_RIGHT_BACK;
  else if( status == "BSY" ) return STATUS_BUSY;
  else if( status == "FLN" ) return STATUS_OFFLINE;
  else if( status == "HDN" ) return STATUS_INVISIBLE;
  else if( status == "IDL" ) return STATUS_IDLE;
  else if( status == "LUN" ) return STATUS_OUT_TO_LUNCH;
  else if( status == "NLN" ) return STATUS_ONLINE;
  else if( status == "PHN" ) return STATUS_ON_THE_PHONE;
  else
  {
    kmWarning() << "Invalid status" << status << "!";
    return STATUS_ONLINE;
  }
}


