/***************************************************************************
                          contactstatusnotification.cpp - notifies when a
                            contact changes their msn status
                             -------------------
    begin                : Saturday July 28 2007
    copyright            : (C) 2007 by Valerio Pilo
    email                : valerio@kmess.org
 ***************************************************************************/

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

#include "../contact/contact.h"
#include "../contact/contactextension.h"
#include "../currentaccount.h"
#include "../kmess.h"
#include "../kmessapplication.h"
#include "../kmessdebug.h"
#include "notificationmanager.h"

#include <QFile>
#include <QTextDocument>

#include <KApplication>
#include <KLocale>
#include <KNotification>
#include <Phonon/MediaObject>



// Class constructor
ContactStatusNotification::ContactStatusNotification( NotificationManager* manager )
: manager_(manager)
{
  // Connect the activation signal to process notification actions
  connect( manager_, SIGNAL( eventActivated(NotificationManager::EventSettings,NotificationManager::Buttons) ),
           this,     SLOT  (       activate(NotificationManager::EventSettings,NotificationManager::Buttons) ) );
}



// Execute the action triggered in a notification
void ContactStatusNotification::activate( NotificationManager::EventSettings settings, NotificationManager::Buttons button )
{
  // The signal wasn't meant for us
  if( settings.sender != this )
  {
    return;
  }

  switch( button )
  {
    case NotificationManager::BUTTON_OPEN_CHAT:
    case NotificationManager::BUTTON_OPEN_OFFLINE_CHAT:
#ifdef KMESSDEBUG_CONTACTSTATUSNOTIFICATION
      kmDebug() << "Opening a chat with" << settings.contact->getHandle();
#endif
      emit startChat( settings.contact->getHandle() );
      break;

    case NotificationManager::BUTTON_HIDE:
#ifdef KMESSDEBUG_CONTACTSTATUSNOTIFICATION
      kmDebug() << "Hiding status notification";
#endif
      // Do nothing
      break;

    default:
#ifdef KMESSDEBUG_CONTACTSTATUSNOTIFICATION
      kmDebug() << "Invalid button" << button;
#endif
      return;
  }
}



// Obtains a status string like "contact has come online" for a MSN status code
const QString ContactStatusNotification::getStatusString( const Status status, const QString& friendlyName ) const
{
  switch( status )
  {
    case STATUS_ONLINE:        return i18n( "<html><b>%1</b><br/>is now online</html>",        friendlyName );
    case STATUS_AWAY:          return i18n( "<html><b>%1</b><br/>has gone away</html>",        friendlyName );
    case STATUS_BE_RIGHT_BACK: return i18n( "<html><b>%1</b><br/>will be right back</html>",   friendlyName );
    case STATUS_BUSY:          return i18n( "<html><b>%1</b><br/>is now busy</html>",          friendlyName );
    case STATUS_INVISIBLE:     return i18n( "<html><b>%1</b><br/>has become invisible</html>", friendlyName ); // Is this one even possible?!
    case STATUS_IDLE:          return i18n( "<html><b>%1</b><br/>has gone idle</html>",        friendlyName );
    case STATUS_OFFLINE:       return i18n( "<html><b>%1</b><br/>has logged out</html>",       friendlyName );
    case STATUS_ON_THE_PHONE:  return i18n( "<html><b>%1</b><br/>is on the phone</html>",      friendlyName );
    case STATUS_OUT_TO_LUNCH:  return i18n( "<html><b>%1</b><br/>is out for lunch</html>",     friendlyName );
    default:
      kmWarning() << "Invalid status" << status << "!";
      return getStatusString( STATUS_ONLINE, friendlyName );
  }
}



// Notify the user about this event (a contact has changed its status)
void ContactStatusNotification::notify( Contact *contact, bool isNeeded )
{
  if( contact == 0 )
  {
    kmWarning() << "Contact is null!";
    return;
  }

  // If notification for this event is disabled
  // or the user decided to don't show the notification about this contact
  // don't show a balloon.
  if( ! isNeeded || contact->getExtension()->getDisableNotifications() )
  {
#ifdef KMESSDEBUG_CONTACTSTATUSNOTIFICATION
    kmDebug() << "Not needed, skipping.";
#endif
    return;
  }

  // KNotify kills formatting by cropping strings in the middle of HTML codes. Remove it.
  const QString& friendlyName = contact->getFriendlyName( STRING_CLEANED_ESCAPED );

  QString text;
  Status  status = contact->getStatus();
  Status  lastStatus = contact->getLastStatus();

#ifdef KMESSDEBUG_CONTACTSTATUSNOTIFICATION
  kmDebug() << "Contact:" << contact->getHandle()
           << "Status:"  << MsnStatus::getCode( lastStatus ) << "->" << MsnStatus::getCode( status );
#endif

  // When contacts go online, whichever may be their status, just show an 'is now online'.
  if( lastStatus == STATUS_OFFLINE && status != STATUS_OFFLINE )
  {
    text = getStatusString( STATUS_ONLINE, friendlyName );
  }
  else
  {
    text = getStatusString( status, friendlyName );
  }

// TODO Fix custom contact sound, possibly using contexts and setComponentData() from KNotification
/*
  // Play a sound
  QString soundPath( contact->getExtension()->getContactSoundPath() );
  QFile   soundFile( soundPath );

  // If a custom audio file exists, play it
  if ( soundFile.exists() )
  {
#ifdef KMESSDEBUG_CONTACTSTATUSNOTIFICATION
    kmDebug() << "Play sound " << soundPath;
#endif

    // Play the custom sound instead of the generic sound
    Phonon::MediaObject* media = Phonon::createPlayer( Phonon::NotificationCategory );
    media->setCurrentSource( soundPath );
    media->play();
  }
*/

  QString eventName;
  if( lastStatus == STATUS_OFFLINE )
  {
    eventName = "contact online";
  }
  else if( status == STATUS_OFFLINE )
  {
    eventName = "contact offline";
  }
  else
  {
    eventName = "contact status";
  }

  // Associate the list events with the contact list window
  const KMessApplication *kmessApp = static_cast<KMessApplication*>( kapp );
  QWidget *mainWindow = kmessApp->getContactListWindow()->window();

  NotificationManager::EventSettings settings;
  settings.sender  = this;
  settings.widget  = mainWindow;
  settings.contact = contact;
  settings.buttons = NotificationManager::BUTTON_HIDE;

  if( status == STATUS_OFFLINE )
  {
    settings.buttons |= NotificationManager::BUTTON_OPEN_OFFLINE_CHAT;
  }
  else
  {
    settings.buttons |= NotificationManager::BUTTON_OPEN_CHAT;
  }

  manager_->notify( eventName, text, settings );
}



#include "contactstatusnotification.moc"
