/***************************************************************************
                          contactframe.cpp  -  description
                             -------------------
    begin                : Thu Jan 16 2003
    copyright            : (C) 2003 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 "contactframe.h"

#include "../contact/contact.h"
#include "../contact/contactextension.h"
#include "../contact/msnstatus.h"
#include "../dialogs/chathistorydialog.h"
#include "../dialogs/contactpropertiesdialog.h"
#include "../model/contactlist.h"
#include "../utils/kmessshared.h"
#include "../utils/richtextparser.h"
#include "../currentaccount.h"
#include "../emoticonmanager.h"
#include "../kmessdebug.h"
#include "chathistorymanager.h"

// HACK: Must go after 2.0-final
#include "../network/msnnotificationconnection.h"
#include "../kmess.h"
#include "../kmessapplication.h"

#include <QClipboard>
#include <QFileInfo>
#include <QMouseEvent>

#include <KApplication>
#include <KActionMenu>
#include <KIconEffect>
#include <KIconLoader>
#include <KMenu>
#include <KStandardDirs>


// Time in milliseconds before the glowing done for a typing user fades away
#define GLOWING_PICTURE_TIMEOUT 5000



// The constructor
ContactFrame::ContactFrame( QWidget *parent )
 : QWidget(parent)
 , Ui::ContactFrame()
 , contact_(0)
 , contactActionPopup_(0)
 , contactPixmapLabelEnabled_(true)
 , contactPropertiesDialog_(0)
 , detailedContact_(0)
 , handle_(QString::null)
 , currentMode_(ModeNormal)
 , infoLabelEnabled_(true)
 , locked_(true)
{
  // Setup the UI as first thing
  setupUi( this );
  layout()->setAlignment( Qt::AlignTop | Qt::AlignLeft );

  // Just for show
  const QPixmap pixmap( KGlobal::dirs()->findResource( "data", "kmess/pics/unknown.png" )  );
  contactPixmapLabel_->setPixmap( pixmap );

  installEventFilter( this );
  contactPixmapLabel_->installEventFilter( this );
  friendlyNameLabel_ ->installEventFilter( this );
  infoLabel_         ->installEventFilter( this );

  // Set up and connect the typing timer
  typingTimer_.setSingleShot( true );
  connect( &typingTimer_, SIGNAL(    timeout() ),
           this,          SLOT  ( stopTyping() ) );
}



ContactFrame::~ContactFrame()
{
  qDeleteAll( copyLinkActionsList_ );
}



// Activate the frame by giving it a contact
void ContactFrame::activate( ContactBase *contact )
{
  // Disconnect the signals linked to previous contact( if there is anyone )
  if ( contact_ != 0 )
  {
    disconnect( contact_, 0, this, 0 );
  }

  if( contact == 0 )
  {
#ifdef KMESSDEBUG_CONTACTFRAME
    kmDebug() << "Deactivating frame for contact:" << handle_;
#endif

    contact_         = 0;
    detailedContact_ = 0;
    locked_          = true;

    qDeleteAll( copyLinkActionsList_ );
    copyLinkActionsList_.clear();
  }
  else
  {
    contact_ = contact;
    handle_  = contact_->getHandle();
    detailedContact_ = CurrentAccount::instance()->getContactList()->getContactByHandle( handle_ );

    // ensure we know when the contact is now invalid.
    connect( contact_, SIGNAL( destroyed(QObject*) ), this, SLOT( contactDestroyed(QObject*) ) );

    if( detailedContact_ != 0 )
    {
      // Connect the contact, to update the frame on presence info changes
      connect( detailedContact_, SIGNAL(    changedList(Contact*)         ),
               this,             SLOT  (    contactChangedList()          ) );
      connect( detailedContact_, SIGNAL(    changedFriendlyName()         ),
               this,             SLOT  (    updateStatusWidgets()         ) );
      connect( detailedContact_, SIGNAL(          changedStatus()         ),
               this,             SLOT  (    updateStatusWidgets()         ) );
      connect( detailedContact_, SIGNAL(         changedPicture()         ),
               this,             SLOT  (          updatePicture()         ) );
      connect( detailedContact_, SIGNAL( changedPersonalMessage(Contact*) ),
               this,             SLOT  (    updateStatusWidgets()         ) );
    }
  }

  // Activate the right-click context menu
  initContactPopup();

  // And prepare the widgets
  updatePicture();
  updateStatusWidgets();

  locked_ = false;

  show();
}



// Allow this contact to see our MSN status
void ContactFrame::allowContact()
{
  if( detailedContact_ == 0 )
  {
    return;
  }

  emit contactAllowed( handle_ );

  locked_ = true;
}



// Foward the changed list signal from contact
void ContactFrame::contactChangedList()
{
  locked_  = false;
  updateStatusWidgets();
}



// The contact was destroyed
void ContactFrame::contactDestroyed( QObject *object )
{
  // This method is relevant for invited contacts, the following happens:
  // - an InvitedContact leaves the chat, SB notifies
  //   - ContactFrame::setDisplayMode() will be called, and updates the widgets.
  //   - CurrentAccount deletes the InvitedContact object.
  // - somehow a code paths leads to this class (Chat::setSwitchboardConnection(0) is already patched).
  //   - crash.

  // adam (17 Jan 2010) - the problem above occurs with InvitedContacts. we attach to the detailedContact_ destroyed() signal
  // rather than the contact_ destroyed() signal. InvitedContact's have detailedContact_ == 0 so we never get notified
  // of the InvitedContact deletion. fixed.

#ifdef KMESSDEBUG_CONTACTFRAME
  if( contact_ && contact_ != object )
  {
    kmWarning() << "Received unexpected contact reference to" << object->metaObject()->className();
  }
  else
  {
    kmDebug() << "Resetting contact reference.";
  }
#else
  Q_UNUSED( object );
#endif

  contact_ = 0;
  detailedContact_ = 0;
}



// Copy some details of the contact to the clipboard.
// Only one method is used to copy all different details, and that's to avoid having three identical methods which only copy different
// text bits on the clipboard.
void ContactFrame::copyText()
{
  // Get the signal sender to find out who called us
  KAction *action = static_cast<KAction*>( const_cast<QObject*>( sender() ) );
  if(KMESS_NULL(action)) return;

  if( action == popupCopyFriendlyName_ )
  {
    kapp->clipboard()->setText( contact_->getFriendlyName( STRING_CLEANED ) );
  }
  else if( action == popupCopyHandle_ )
  {
    kapp->clipboard()->setText( handle_ );
  }
  else if( action == popupCopyPersonalMessage_ && detailedContact_ != 0 )
  {
    kapp->clipboard()->setText( detailedContact_->getPersonalMessage( STRING_CLEANED ) );
  }
  else if( action == popupCopyMusic_ && detailedContact_ != 0 )
  {
    kapp->clipboard()->setText( detailedContact_->getCurrentMediaString() );
  }
  else if( detailedContact_ != 0 )
  {
    // Copy the link from PM or Friendly Name
    kapp->clipboard()->setText( action->toolTip() );
  }
}



// The personal status message received an event.
bool ContactFrame::eventFilter( QObject *obj, QEvent *event )
{
  int eventType = event->type();

  // Check if the obj is contactPixmapLabel
  if( obj == contactPixmapLabel_ && detailedContact_ )
  {
    // Apply glow effect to image
    if( eventType == QEvent::Enter )
    {
      QImage image( detailedContact_->getContactPicturePath() );
      KIconEffect::toGamma( image, 0.8f );
      contactPixmapLabel_->setPixmap( QPixmap::fromImage( image ) );
    }
    else if( eventType == QEvent::Leave && !typingTimer_.isActive() )
    {
      QImage image( detailedContact_->getContactPicturePath() );

      // Only disable glow effect when the contact is not typing
      contactPixmapLabel_->setPixmap( QPixmap::fromImage( image ) );
    }
    else if ( eventType == QEvent::DragEnter )
    {
      QDragEnterEvent *dragEvent = static_cast<QDragEnterEvent*>( event );
      const QMimeData *mimeData = dragEvent->mimeData();

      // The mimeData object can contain one of the following objects: an image, HTML text, plain text, or a list of URLs.
      // We need only the first URL object
      if( mimeData->hasUrls() )
      {
        dragEvent->acceptProposedAction();
      }
      else
      {
        dragEvent->ignore();
      }
    }
    else if ( eventType == QEvent::Drop )
    {
      QDropEvent* dropEvent = static_cast<QDropEvent*>( event );
      const QMimeData *mimeData = dropEvent->mimeData();

      // The mimeData object can contain one of the following objects: an image, HTML text, plain text, or a list of URLs.
      // We need only the first URL object
      if( ! mimeData->hasUrls() )
      {
        return true;
      }

      QUrl mimeUrl = mimeData->urls().first();
      QString filePath;
      QPixmap pictureData;

      if( mimeUrl.isEmpty() )
      {
        kmWarning() << "Dropped empty MIME URL";
        return true;
      }

      filePath = mimeUrl.path();

      if( ! pictureData.load( filePath ) )
      {
        kmWarning() << "The file dropped is not an image or doesn't exist";
        return true;
      }

      detailedContact_->getExtension()->setContactAlternativePicturePath( filePath );

      dropEvent->acceptProposedAction();
    }
  }

  if( eventType != QEvent::MouseButtonRelease )
  {
    return false;  // don't stop processing.
  }

  const QMouseEvent *mouseEvent = static_cast<QMouseEvent*>( event );

  // Show the menu regardlessly of where the mouse button has been pressed
  showContactPopup( mouseEvent->globalPos() );

  return false;  // don't stop processing.
}



// Return the handle of this frame's contact
const QString& ContactFrame::getHandle() const
{
  return handle_;
}



// Initialize the contact popup
bool ContactFrame::initContactPopup()
{
  // Check if there is a valid contact_ and if contact action menu was already initialized
  if( contact_ == 0 || contactActionPopup_ != 0 )
  {
    return false;
  }

  // Initialize context popup actions
  popupStartPrivateChat_    = new KAction( KIcon("user-group-new"),           i18n("&Start Private Chat"), this );
  popupEmailContact_        = new KAction( KIcon("mail-message-new"),         i18n("&Send Email"),         this );
  popupShowHistory_         = new KAction( KIcon("chronometer"),              i18n("Chat &History"),       this );
  popupMsnProfile_          = new KAction( KIcon("preferences-desktop-user"), i18n("&View Profile"),       this );
  popupContactProperties_   = new KAction( KIcon("user-properties"),          i18n("&Properties"),         this );

  popupAddContact_          = new KAction( KIcon("list-add"),         i18n("&Add Contact"),      this );
  popupAllowContact_        = new KAction( KIcon("dialog-ok-apply"),  i18n("A&llow Contact"),    this );
  popupRemoveContact_       = new KAction( KIcon("list-remove-user"), i18n("&Delete Contact"),   this );

  popupBlockContact_        = new KAction( KIcon("dialog-cancel"),    i18n("&Block Contact"),    this );
  popupUnblockContact_      = new KAction( KIcon("dialog-ok"),        i18n("&Unblock Contact"),  this );

  popupCopyFriendlyName_    = new KAction(                            i18n("&Friendly Name"),    this );
  popupCopyPersonalMessage_ = new KAction(                            i18n("&Personal Message"), this );
  popupCopyHandle_          = new KAction(                            i18n("&Email Address"),    this );
  popupCopyMusic_           = new KAction(                            i18n("Song &Name"),        this );

  popupPropGeneral_         = new KAction( KIcon("user-properties"),  i18n("&Information"),      this );
  popupPropImages_          = new KAction( KIcon("draw-brush"),       i18n("Display Pictures"),  this );
  popupPropNotes_           = new KAction( KIcon("document-edit"),    i18n("&Notes"),            this );
  popupPropEmoticons_       = new KAction( KIcon("face-smile"),       i18n("&Emoticons"),        this );


  // Connect the actions
  connect( popupStartPrivateChat_,    SIGNAL(triggered( bool )), this,  SLOT( slotStartPrivateChat()  ) );

  connect( popupEmailContact_,        SIGNAL(triggered(bool)),   this,  SLOT( sendEmail()             ) );
  connect( popupShowHistory_,         SIGNAL(triggered(bool)),   this,  SLOT( showChatHistory()       ) );
  connect( popupMsnProfile_,          SIGNAL(triggered(bool)),   this,  SLOT( showProfile()           ) );

  connect( popupAddContact_,          SIGNAL(triggered(bool)),   this,  SLOT( toggleContactAdded()    ) );
  connect( popupAllowContact_,        SIGNAL(triggered(bool)),   this,  SLOT( allowContact()          ) );
  connect( popupRemoveContact_,       SIGNAL(triggered(bool)),   this,  SLOT( toggleContactAdded()    ) );

  connect( popupBlockContact_,        SIGNAL(triggered(bool)),   this,  SLOT( toggleContactBlocked()  ) );
  connect( popupUnblockContact_,      SIGNAL(triggered(bool)),   this,  SLOT( toggleContactBlocked()  ) );

  connect( popupCopyFriendlyName_,    SIGNAL(triggered(bool)),   this,  SLOT( copyText()              ) );
  connect( popupCopyPersonalMessage_, SIGNAL(triggered(bool)),   this,  SLOT( copyText()              ) );
  connect( popupCopyHandle_,          SIGNAL(triggered(bool)),   this,  SLOT( copyText()              ) );
  connect( popupCopyMusic_,           SIGNAL(triggered(bool)),   this,  SLOT( copyText()              ) );

  connect( popupPropGeneral_,         SIGNAL(triggered(bool)),   this,  SLOT( showContactProperties() ) );
  connect( popupPropImages_,          SIGNAL(triggered(bool)),   this,  SLOT( showContactProperties() ) );
  connect( popupPropNotes_,           SIGNAL(triggered(bool)),   this,  SLOT( showContactProperties() ) );
  connect( popupPropEmoticons_,       SIGNAL(triggered(bool)),   this,  SLOT( showContactProperties() ) );

  // Initialize sub popups
  popupCopyMenu_ = new KActionMenu( i18n("&Copy"), this );
  popupCopyMenu_ ->addAction( popupCopyFriendlyName_ );
  popupCopyMenu_ ->addAction( popupCopyPersonalMessage_ );
  popupCopyMenu_ ->addAction( popupCopyHandle_ );
  popupCopyMenu_ ->addAction( popupCopyMusic_ );
  popupCopyMenu_ ->addSeparator();

  popupPropMenu_ = new KActionMenu( i18n("&Properties"), this );
  popupPropMenu_ ->addAction( popupPropGeneral_   );
  popupPropMenu_ ->addAction( popupPropImages_    );
  popupPropMenu_ ->addAction( popupPropNotes_     );
  popupPropMenu_ ->addAction( popupPropEmoticons_ );

  // Initialize the popup popup
  contactActionPopup_ = new KMenu( handle_, this );

  // Attach the actions to the menu
  // Order is as consistent as possible with the menu in KMessView
  contactActionPopup_->addTitle( contact_->getHandle() );
  contactActionPopup_->addAction( popupStartPrivateChat_ );
  contactActionPopup_->addAction( popupEmailContact_ );
  contactActionPopup_->addAction( popupShowHistory_ );
  contactActionPopup_->addAction( popupMsnProfile_ );
  contactActionPopup_->addAction( popupCopyMenu_ );
  contactActionPopup_->addSeparator();

  contactActionPopup_->addAction( popupAddContact_ );
  contactActionPopup_->addAction( popupAllowContact_ );

  contactActionPopup_->addAction( popupBlockContact_ );
  contactActionPopup_->addAction( popupUnblockContact_ );

  contactActionPopup_->addAction( popupRemoveContact_ );

  contactActionPopup_->addSeparator();

  contactActionPopup_->addAction( popupPropMenu_ );

  return true;
}



// The user received a message from this contact
void ContactFrame::messageReceived()
{
  // Stop the "user is typing" glow
  typingTimer_.stop();
  stopTyping();
}



// Email the contact
void ContactFrame::sendEmail()
{
  if ( contact_ != 0 )
  {
    CurrentAccount::instance()->openMailAtCompose( handle_ );
  }
}



// Change the display mode of the frame when the contact leaves the chat or there are many active contacts
void ContactFrame::setDisplayMode( DisplayMode mode )
{
  if( currentMode_ == mode )
  {
    return;
  }

  // Save the new current mode to avoid useless updates
  currentMode_ = mode;

#ifdef KMESSDEBUG_CONTACTFRAME
  kmDebug() << "Frame mode:" << mode;
#endif

  // Change the displayed widgets
  switch( mode )
  {
    case ModeSingle:
      popupStartPrivateChat_->setVisible( false );
      contactPixmapLabelEnabled_ = true;
      infoLabelEnabled_          = true;
      break;

    case ModeNormal:
      popupStartPrivateChat_->setVisible( true );
      contactPixmapLabelEnabled_ = true;
      infoLabelEnabled_          = true;
      break;

    case ModeSmall:
      popupStartPrivateChat_->setVisible( true );
      contactPixmapLabelEnabled_ = false;
      infoLabelEnabled_          = true;
      break;

    case ModeTiny:
      popupStartPrivateChat_->setVisible( true );
      contactPixmapLabelEnabled_ = false;
      infoLabelEnabled_          = false;
      break;
  }

  // Update the status widgets
  updateStatusWidgets();
}



// Enable or disable the frame
void ContactFrame::setEnabled( bool isEnabled )
{
  contactPixmapLabel_->setEnabled( isEnabled );
}



// Show the contact's chat history
void ContactFrame::showChatHistory()
{
  ChatHistoryDialog *dialog = new ChatHistoryDialog( this );
  dialog->setInitialContact( CurrentAccount::instance()->getHandle(), handle_ );
  dialog->show();
}



// Update and show the contact popup menu
void ContactFrame::showContactPopup( const QPoint &point )
{
  bool isAdded     = false;
  bool isAllowed   = false;
  bool isBlocked   = false;
  bool hasPersonalMessage = false;
  bool hasMediaMessage = false;

  // If detailed contact information is available
  if( detailedContact_ != 0 )
  {
    // We have the contact already in our list, but is possible to block/allow/unblock it
    isAdded   = detailedContact_->isFriend();
    isAllowed = detailedContact_->isAllowed();
    isBlocked = detailedContact_->isBlocked();

    hasPersonalMessage = ! detailedContact_->getPersonalMessage().isEmpty();
    hasMediaMessage = ! detailedContact_->getCurrentMediaString().isEmpty();

    // Search for links
    qDeleteAll( copyLinkActionsList_ );
    copyLinkActionsList_.clear();

    // Append friendly name and personal message so cycle only one time to search links
    const QString nameAndPm( detailedContact_->getFriendlyName() + " " + detailedContact_->getPersonalMessage() );
    QStringList links;

    //Initialize index, link RegExp and found boolean for insert separator only at first found link
    int pos = 0;
    QRegExp linkRegExp( "(http://|https://|ftp://|sftp://|www\\..)\\S+" );
    QString foundLink;

    while( ( pos = linkRegExp.indexIn( nameAndPm, pos ) ) != -1 )
    {
      // Grep the found link and update the position for the next cycle
      foundLink =linkRegExp.cap( 0 );
      pos += linkRegExp.matchedLength();

      // Skip duplicated links
      if( links.contains( foundLink ) )
      {
        continue;
      }
      links.append( foundLink );

      // Put the found link into KAction, replace & with && to avoid shortcut problem and use tooltip
      // for future grep of link ( to avoid shortcut problem too )
      popupCopyLink_ = new KAction( foundLink.replace( "&", "&&" ), this );
      popupCopyLink_->setToolTip( foundLink );
      connect( popupCopyLink_, SIGNAL( triggered( bool ) ), this, SLOT( copyText() ) );

      // Append current KAction to the copy link list
      copyLinkActionsList_.append( popupCopyLink_ );

      // Add action to copy menu
      popupCopyMenu_->addAction( popupCopyLink_ );
    }
  }

  popupShowHistory_        ->setEnabled( ChatHistoryManager::contactsList().contains( handle_ ) );

  popupContactProperties_  ->setVisible( detailedContact_ != 0 );
  popupMsnProfile_         ->setVisible( detailedContact_ != 0 );

  popupAllowContact_       ->setVisible( ! isAllowed && ! isAdded && detailedContact_ != 0 );
  popupCopyPersonalMessage_->setVisible( hasPersonalMessage );
  popupCopyMusic_          ->setVisible( hasMediaMessage );

  popupAddContact_         ->setVisible( ! locked_   && ! isAdded   );
  popupRemoveContact_      ->setVisible( ! locked_   &&   isAdded   );

  popupBlockContact_       ->setVisible( ! locked_ && ! isBlocked && detailedContact_ != 0 );
  popupUnblockContact_     ->setVisible( ! locked_ &&   isBlocked );

  contactActionPopup_->popup( point );
}



// Show the contact properties window
void ContactFrame::showContactProperties()
{
  // Check if there are details for contact
  if( detailedContact_ != 0 && detailedContact_->getExtension() != 0 )
  {
    // Default is not to open notes tab
    ContactPropertiesDialog::DefaultTab defaultTab = ContactPropertiesDialog::Information;

    // If we've been called via a specialized properties action,
    // open the corresponding tab
    if( sender() == popupPropEmoticons_ )
    {
      defaultTab = ContactPropertiesDialog::Emoticons;
    }
    else if( sender() == popupPropImages_ )
    {
      defaultTab = ContactPropertiesDialog::Images;
    }
    else if( sender() == popupPropNotes_ )
    {
      defaultTab = ContactPropertiesDialog::Notes;
    }

    // the qlistwidget in the dialog doesn't seem to handle being reopened from
    // a saved instance (unknown why). it causes display issues (i.e., displays the same
    // groups multiple times or doesn't display them at all). This resolves the problem.
    ContactPropertiesDialog *dialog = new ContactPropertiesDialog(this);

    KMess *kmess = static_cast<KMessApplication*>( kapp )->getContactListWindow();

    // HACK: MUST GO AFTER 2.0-final!!
    connect( dialog, SIGNAL(addContactToGroup(QString, QString)),
             kmess->getNsConnection(), SLOT( addContactToGroup(QString, QString) ) );

    connect( dialog, SIGNAL(removeContactFromGroup(QString, QString)),
             kmess->getNsConnection(), SLOT( removeContactFromGroup(QString, QString) ) );

    dialog->launch( detailedContact_, defaultTab );

    delete dialog;
  }
}



// Show the contact's profile
void ContactFrame::showProfile()
{
  if( contact_ == 0 )
  {
    return;
  }

  // Create a URL to the msn profile page, localized with our system's locale.
  const KUrl url( "http://members.msn.com/default.msnw?mem=" + handle_ + "&mkt=" + KGlobal::locale()->language() );

  // Launch the browser for the given URL
  KMessShared::openBrowser( url );
}



// Request to start private chat
void ContactFrame::slotStartPrivateChat()
{
  emit startPrivateChat( handle_ );
}



// Receive notice that the contact is typing
void ContactFrame::startTyping()
{
  contactPixmapLabel_->setPixmap( contactTypingPicture_ );

  // Make the contact picture glow
  // Start the timer to disable the label
  typingTimer_.start( GLOWING_PICTURE_TIMEOUT );
}



// Disable the typing label when the timer has timed out
void ContactFrame::stopTyping()
{
  contactPixmapLabel_->setPixmap( contactPicture_ );
}



// Add or remove the contact from the contact list
void ContactFrame::toggleContactAdded()
{
  if( detailedContact_ == 0 )
  {
    emit contactAdded( handle_, true );
  }
  else
  {
    emit contactAdded( handle_, ! detailedContact_->isFriend() );
  }

  // Disallow adding unknown contacts more than once
  locked_ = true;
}



// Change the contact's blocked/unblocked status
void ContactFrame::toggleContactBlocked()
{
  if( detailedContact_ == 0 )
  {
    emit contactBlocked( handle_, true );
  }
  else
  {
    emit contactBlocked( handle_, ! detailedContact_->isBlocked() );
  }

  // Disallow adding unknown contacts more than once
  locked_ = true;
}



// Update the contact picture
void ContactFrame::updatePicture()
{
  if ( contact_ == 0 )
  {
    return;
  }

  // See if the contact picture is not updated. Avoids GUI flashing on older boxes
  const QString   contactPicturePath( contact_->getContactPicturePath() );
  const QFileInfo contactPictureInfo( contactPicturePath );
  const QDateTime contactPictureDate( contactPictureInfo.lastModified() );

  if( contactPicturePath == contactPicturePath_
  &&  contactPictureDate == contactPictureDate_ )
  {
#ifdef KMESSDEBUG_CONTACTFRAME
    kmDebug() << "Picture was already loaded.";
#endif
    return;
  }

#ifdef KMESSDEBUG_CONTACTFRAME
  kmDebug() << "New contact picture:" << contactPicturePath;
#endif

  QImage contactImage( contactPicturePath );
  bool loaded = ! contactImage.isNull();
  if( loaded )
  {
    // Loaded
    contactPicturePath_ = contactPicturePath;
    contactPictureDate_ = contactPictureDate;
  }
  else
  {
    // Not loaded (PNG error?). load default if custom image could not be loaded
    loaded = contactImage.load( contact_->getContactDefaultPicturePath() );

    if( ! loaded )
    {
      return;
    }
  }

  // Setup the normal and typing pixmaps
  contactPicture_ = QPixmap::fromImage( contactImage );
  KIconEffect::toGamma( contactImage, 0.8f );
  contactTypingPicture_ = QPixmap::fromImage( contactImage );

  // Display the image
  contactPixmapLabel_->setPixmap( contactPicture_ );
}



// Update the status widgets
void ContactFrame::updateStatusWidgets()
{
  if( contact_ == 0 )
  {
    return;
  }

  QString label, statusIdentifier;
  const Status  status( contact_->getStatus() );
  Flags   flags = FlagNone;

  if( detailedContact_ != 0 && detailedContact_->isBlocked())
  {
    // Show blocked regardless of status
    statusIdentifier = i18n( "Blocked" );
    flags = FlagBlocked;
  }
  else
  {
    statusIdentifier = MsnStatus::getName( status );
  }

  friendlyNameLabel_->setText( contact_->getFriendlyName( STRING_CHAT_SETTING_ESCAPED ) );
  friendlyNameLabel_->setToolTip( contact_->getFriendlyName() );
  statusPixmapLabel_->setToolTip( i18nc( "Tooltip for a contact's status icon, "
                                          "arg %1 is the Live Messenger status, like 'Online'",
                                          "The contact is %1",
                                          statusIdentifier ) );
  statusPixmapLabel_->setPixmap( MsnStatus::getIcon( status, flags ) );

  // Update the informative label
  if( detailedContact_ && infoLabelEnabled_ )
  {
    const QString& mediaString = detailedContact_->getCurrentMediaString();
    const QString& messageString = detailedContact_->getPersonalMessage( STRING_CHAT_SETTING_ESCAPED );
    if( ! mediaString.isEmpty() )
    {
      // Determine the icon for the various media types, if none no icon will be shown
      QString mediaEmoticon;
      const QString& mediaType = detailedContact_->getCurrentMediaType();
      if( mediaType == "Music" )
      {
        mediaEmoticon = EmoticonManager::instance()->getReplacement( "(8)", true );
      }
      else if( mediaType == "Gaming" )
      {
        mediaEmoticon = EmoticonManager::instance()->getReplacement( "(xx)", true );
      }

      infoLabel_->setVisible( true );
      infoLabel_->setText( mediaEmoticon + Qt::escape( mediaString ) );
      infoLabel_->setToolTip( mediaString );
    }
    else if( ! messageString.isEmpty() )
    {
      infoLabel_->setVisible( true );
      infoLabel_->setText( messageString );
      infoLabel_->setToolTip( detailedContact_->getPersonalMessage( STRING_CLEANED ) );
    }
    else
    {
      infoLabel_->setVisible( false );
    }
  }
  else
  {
    infoLabel_->setVisible( false );
  }

  contactPixmapLabel_->setVisible( contactPixmapLabelEnabled_ );
}



#include "contactframe.moc"
