/***************************************************************************
                          chatnotification.cpp -  notifies when a
                            contact communicates with the user
                             -------------------
    begin                : Tuesday April 10 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 "chatnotification.h"

#include "../chat/chat.h"
#include "../chat/chatwindow.h"
#include "../contact/contactextension.h"
#include "../contact/invitedcontact.h"
#include "../model/contactlist.h"
#include "../network/chatmessage.h"
#include "../kmessdebug.h"
#include "../currentaccount.h"
#include "notificationmanager.h"

#include <QPixmap>

#include <KNotification>
#include <KWindowSystem>


// How long a message can be without being cropped away
#define MAX_BALLOON_MESSAGE_SIZE      64



// Class constructor
ChatNotification::ChatNotification( 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 ChatNotification::activate( NotificationManager::EventSettings settings, NotificationManager::Buttons button )
{
  // The signal wasn't meant for us
  if( settings.sender != this )
  {
    return;
  }

  switch( button )
  {
    case NotificationManager::BUTTON_VIEW_MESSAGE:
#ifdef KMESSDEBUG_CHATNOTIFICATION
      kmDebug() << "Raising chat with" << settings.contact->getHandle();
#endif
      emit raiseChat( static_cast<Chat*>( settings.widget ), true );
      break;

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

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



// Notify the user about this event (a contact has contacted the user)
void ChatNotification::notify( const ChatMessage &message, Chat *chat )
{
  // End if the event is coming from us instead of from a contact
  if( ! message.isIncoming() )
  {
#ifdef KMESSDEBUG_CHATNOTIFICATION
    kmDebug() << "Not displaying a popup for an outgoing message.";
#endif
    return;
  }

  // Check the chat pointer, we need it
  if( ! chat )
  {
#ifdef KMESSDEBUG_CHATNOTIFICATION
    kmDebug() << "Invalid pointer to chat window.";
#endif
    return;
  }

  // Verify if the chat is active, and if so don't notify anything
  if( KWindowSystem::activeWindow() == chat->getChatWindow()->winId()
  &&  chat == chat->getChatWindow()->getCurrentChat() )
  {
#ifdef KMESSDEBUG_CHATNOTIFICATION
    kmDebug() << "Window is active, skipping.";
#endif
    return;
  }


  QString         text;
  int             messageType = message.getType();
  QString         body( message.getBody() );
  const QString  &handle = message.getContactHandle();
  CurrentAccount *currentAccount = CurrentAccount::instance();
  ContactBase    *contact;

  Contact *contactDetail = currentAccount->getContactList()->getContactByHandle( handle );
  if( contactDetail != 0 )
  {
    if( contactDetail->getExtension()->getDisableNotifications() )
    {
      kmDebug() << "The contact: " << handle << " has the notification disabled, skip it";
      return;
    }
    contact = static_cast<ContactBase*> (contactDetail);
  }
  else
  {
    contact = currentAccount->getContactByHandle( handle );
  }

  // When the contact doesn't exist, only use the handle
  if( contact == 0 )
  {
    contact = currentAccount->addInvitedContact( handle );
  }

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

#ifdef KMESSDEBUG_CHATNOTIFICATION
  kmDebug() << "Contact" << handle;
#endif

  // Truncate the message so it doesn't make the balloon too big
  if( body.length() > MAX_BALLOON_MESSAGE_SIZE )
  {
    body.truncate( MAX_BALLOON_MESSAGE_SIZE );
    body += " ...";
  }

  // Set the balloon text to a generic message, which will be overridden with more useful messages, if available
  switch( messageType )
  {
    case ChatMessage::TYPE_PRESENCE:
    case ChatMessage::TYPE_NOTIFICATION:
      text = i18n( "<html>In <b>%1</b>'s chat:<br/>%2</html>", friendlyName, body );
      break;

    case ChatMessage::TYPE_INCOMING:
      text = i18n( "<html><b>%1</b> says:<br/>'%2'</html>", friendlyName, body );
      break;

    case ChatMessage::TYPE_OFFLINE_INCOMING:
      text = i18n( "<html><b>%1</b> has sent you an offline message:<br/>'%2'</html>", friendlyName, body );
      break;

    case ChatMessage::TYPE_APPLICATION:
    case ChatMessage::TYPE_APPLICATION_FILE:
      text = i18n( "<html>%1's chat requests attention!</html>", friendlyName );
      break;

    case ChatMessage::TYPE_SYSTEM:
    default:
      text = i18n( "<html><b>%1</b>:<br/>%2</html>", friendlyName, body );
      break;
  }

  switch( message.getContentsClass() )
  {
    case ChatMessage::CONTENT_MESSAGE_INK:
      text = i18n( "<html><b>%1</b> has sent you a handwritten message!</html>", friendlyName );
      break;

    case ChatMessage::CONTENT_NOTIFICATION_NUDGE:
      text = i18n( "<html><b>%1</b> has sent you a nudge!</html>", friendlyName );
      break;

    case ChatMessage::CONTENT_NOTIFICATION_WINK:
      text = i18n( "<html><b>%1</b> has sent you a wink!</html>", friendlyName );
      break;

    case ChatMessage::CONTENT_APP_INVITE:
      switch( messageType )
      {
        case ChatMessage::TYPE_APPLICATION_FILE: text = i18n( "<html><b>%1</b> is sending you a file!</html>", friendlyName ); break;
        default: text = i18n( "<html><b>%1</b> has sent you an invitation!</html>", friendlyName ); break;
      }
      break;

    case ChatMessage::CONTENT_APP_CANCELED:
      switch( messageType )
      {
        case ChatMessage::TYPE_APPLICATION_FILE: text = i18n( "<html><b>%1</b> has canceled the file transfer!</html>", friendlyName ); break;
        default: text = i18n( "<html><b>%1</b>'s activity has been canceled!</html>", friendlyName ); break;
      }
      break;

    case ChatMessage::CONTENT_APP_STARTED:
      switch( messageType )
      {
        case ChatMessage::TYPE_APPLICATION_FILE: text = i18n( "<html><b>%1</b> has accepted the file transfer!</html>", friendlyName ); break;
        default: text = i18n( "<html><b>%1</b> has accepted your invitation!</html>", friendlyName ); break;
      }
      break;

    case ChatMessage::CONTENT_APP_ENDED:
      switch( messageType )
      {
        case ChatMessage::TYPE_APPLICATION_FILE: text = i18n( "<html>The file transfer with <b>%1</b> is done!</html>", friendlyName ); break;
        default: text = i18n( "<html><b>%1</b>'s activity has ended!</html>", friendlyName ); break;
      }
      break;

    case ChatMessage::CONTENT_APP_FAILED:
      switch( messageType )
      {
        case ChatMessage::TYPE_APPLICATION_FILE: text = i18n( "<html>The file transfer with <b>%1</b> has failed!</html>", friendlyName ); break;
        default: text = i18n( "<html><b>%1</b>'s activity has ended with an error!</html>", friendlyName ); break;
      }
      break;

    default:
      break;
  }

  QString eventName;
  if( message.getContentsClass() == ChatMessage::CONTENT_NOTIFICATION_NUDGE )
  {
    eventName = "nudge";
  }
  else if( messageType == ChatMessage::TYPE_INCOMING && chat->isChatFirstMessage() )
  {
    eventName = "chat start";
  }
  else
  {
    eventName = "new message";
  }

  NotificationManager::EventSettings settings;
  settings.sender  = this;
  settings.widget  = chat;
  settings.contact = contact;
  settings.buttons = NotificationManager::BUTTON_HIDE | NotificationManager::BUTTON_VIEW_MESSAGE;

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



#include "chatnotification.moc"
