/*
    This file is part of libtdepim.

    Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.
*/

#include <tqbuffer.h>
#include <tqimage.h>
#include <tqpopupmenu.h>
#include <tqurl.h>

#include <tdeabc/address.h>
#include <tdeabc/addressee.h>
#include <tdeabc/phonenumber.h>
#include <tdeabc/resource.h>
#include <tdeactionclasses.h>
#include <tdeapplication.h>
#include <tdeconfig.h>
#include <tdeglobal.h>
#include <tdeglobalsettings.h>
#include <kiconloader.h>
#include <tdeio/job.h>
#include <tdelocale.h>
#include <kmdcodec.h>
#include <tdemessagebox.h>
#include <krun.h>
#include <kstringhandler.h>
#include <tdetempfile.h>

#include <kdebug.h>

#include "addresseeview.h"
#include "sendsmsdialog.h"
#include "resourceabc.h"

using namespace KPIM;

AddresseeView::AddresseeView( TQWidget *parent, const char *name,
                              TDEConfig *config )
  : KTextBrowser( parent, name ), mDefaultConfig( false ), mImageJob( 0 ),
    mLinkMask( AddressLinks | EmailLinks | PhoneLinks | URLLinks | IMLinks | CustomFields )
{
  setWrapPolicy( TQTextEdit::AtWordBoundary );
  setLinkUnderline( false );
  setVScrollBarMode( TQScrollView::AlwaysOff );
  setHScrollBarMode( TQScrollView::AlwaysOff );

  TQStyleSheet *sheet = styleSheet();
  TQStyleSheetItem *link = sheet->item( "a" );
  link->setColor( TDEGlobalSettings::linkColor() );

  connect( this, TQ_SIGNAL( mailClick( const TQString&, const TQString& ) ),
           this, TQ_SLOT( slotMailClicked( const TQString&, const TQString& ) ) );
  connect( this, TQ_SIGNAL( urlClick( const TQString& ) ),
           this, TQ_SLOT( slotUrlClicked( const TQString& ) ) );
  connect( this, TQ_SIGNAL( highlighted( const TQString& ) ),
           this, TQ_SLOT( slotHighlighted( const TQString& ) ) );

  setNotifyClick( true );

  mActionShowBirthday = new TDEToggleAction( i18n( "Show Birthday" ) );
  mActionShowBirthday->setCheckedState( i18n( "Hide Birthday" ) );
  mActionShowAddresses = new TDEToggleAction( i18n( "Show Postal Addresses" ) );
  mActionShowAddresses->setCheckedState( i18n( "Hide Postal Addresses" ) );
  mActionShowEmails = new TDEToggleAction( i18n( "Show Email Addresses" ) );
  mActionShowEmails->setCheckedState( i18n( "Hide Email Addresses" ) );
  mActionShowPhones = new TDEToggleAction( i18n( "Show Telephone Numbers" ) );
  mActionShowPhones->setCheckedState( i18n( "Hide Telephone Numbers" ) );
  mActionShowURLs = new TDEToggleAction( i18n( "Show Web Pages (URLs)" ) );
  mActionShowURLs->setCheckedState( i18n( "Hide Web Pages (URLs)" ) );
  mActionShowIMAddresses = new TDEToggleAction( i18n( "Show Instant Messaging Addresses" ) );
  mActionShowIMAddresses->setCheckedState( i18n( "Hide Instant Messaging Addresses" ) );
  mActionShowCustomFields = new TDEToggleAction( i18n( "Show Custom Fields" ) );
  mActionShowCustomFields->setCheckedState( i18n( "Hide Custom Fields" ) );

  connect( mActionShowBirthday, TQ_SIGNAL( toggled( bool ) ), TQ_SLOT( configChanged() ) );
  connect( mActionShowAddresses, TQ_SIGNAL( toggled( bool ) ), TQ_SLOT( configChanged() ) );
  connect( mActionShowEmails, TQ_SIGNAL( toggled( bool ) ), TQ_SLOT( configChanged() ) );
  connect( mActionShowPhones, TQ_SIGNAL( toggled( bool ) ), TQ_SLOT( configChanged() ) );
  connect( mActionShowURLs, TQ_SIGNAL( toggled( bool ) ), TQ_SLOT( configChanged() ) );
  connect( mActionShowIMAddresses, TQ_SIGNAL( toggled( bool ) ), TQ_SLOT( configChanged() ) );
  connect( mActionShowCustomFields, TQ_SIGNAL( toggled( bool ) ), TQ_SLOT( configChanged() ) );

  if ( !config ) {
    mConfig = new TDEConfig( "kaddressbookrc" );
    mDefaultConfig = true;
  } else
    mConfig = config;

  load();

  // set up IMProxy to display contacts' IM presence and make connections to keep the display live
  mKIMProxy = ::KIMProxy::instance( tdeApp->dcopClient() );
  connect( mKIMProxy, TQ_SIGNAL( sigContactPresenceChanged( const TQString& ) ),
           this, TQ_SLOT( slotPresenceChanged( const TQString& ) ) );
  connect( mKIMProxy, TQ_SIGNAL( sigPresenceInfoExpired() ),
           this, TQ_SLOT( slotPresenceInfoExpired() ) );
}

AddresseeView::~AddresseeView()
{
  if ( mDefaultConfig )
    delete mConfig;
  mConfig = 0;

  delete mActionShowBirthday;
  delete mActionShowAddresses;
  delete mActionShowEmails;
  delete mActionShowPhones;
  delete mActionShowURLs;
  delete mActionShowIMAddresses;
  delete mActionShowCustomFields;

  mKIMProxy = 0;
}

void AddresseeView::setAddressee( const TDEABC::Addressee& addr )
{
  mAddressee = addr;

  if ( mImageJob ) {
    mImageJob->kill();
    mImageJob = 0;
  }

  mImageData.truncate( 0 );

  updateView();
}

void AddresseeView::enableLinks( int linkMask )
{
  mLinkMask = linkMask;
}

TQString AddresseeView::vCardAsHTML( const TDEABC::Addressee& addr, ::KIMProxy *proxy, LinkMask linkMask,
                                    bool internalLoading, FieldMask fieldMask )
{
  TQString image = TQString( "contact_%1_image" ).arg( addr.uid() );

  // Style strings from Gentix; this is just an initial version.
  //
  // These will be substituted into various HTML strings with .arg().
  // Search for @STYLE@ to find where. Note how we use %1 as a
  // placeholder where we fill in something else (in this case,
  // the global background color).
  //
  TQString backgroundColor = TDEGlobalSettings::alternateBackgroundColor().name();
  TQString cellStyle = TQString::fromLatin1(
        "style=\""
        "padding-right: 2px; "
        "border-right: #000 dashed 1px; "
        "background: %1;\"").arg(backgroundColor);
  TQString backgroundColor2 = TDEGlobalSettings::baseColor().name();
  TQString cellStyle2 = TQString::fromLatin1(
        "style=\""
        "padding-left: 2px; "
        "background: %1;\"").arg(backgroundColor2);
  TQString tableStyle = TQString::fromLatin1(
        "style=\""
        "border: solid 1px; "
        "margin: 0em;\"");

  // We'll be building a table to display the vCard in.
  // Each row of the table will be built using this string for its HTML.
  //
  TQString rowFmtStr = TQString::fromLatin1(
        "<tr>"
        "<td align=\"right\" valign=\"top\" width=\"30%\" "); // Tag unclosed
  rowFmtStr.append( cellStyle );
  rowFmtStr.append( TQString::fromLatin1(
	">" // Close tag
        "<b>%1</b>"
        "</td>"
        "<td align=\"left\" valign=\"top\" width=\"70%\" ") ); // Tag unclosed
  rowFmtStr.append( cellStyle2 );
  rowFmtStr.append( TQString::fromLatin1(
	">" // Close tag
        "%2"
        "</td>"
        "</tr>\n"
        ) );

  // Build the table's rows here
  TQString dynamicPart;


  if ( !internalLoading ) {
    TDEABC::Picture pic = addr.photo();
    if ( pic.isIntern() && !pic.data().isNull() ) {
      image = pixmapAsDataUrl( pic.data() );
    } else if ( !pic.url().isEmpty() ) {
      image = (pic.url().startsWith( "http://" ) || pic.url().startsWith( "https://" ) ? pic.url() : "http://" + pic.url());
    } else {
      image = "file:" + TDEGlobal::iconLoader()->iconPath( "preferences-desktop-personal", TDEIcon::Desktop );
    }
  }

  if ( fieldMask & BirthdayFields ) {
    TQDate date = addr.birthday().date();

    if ( date.isValid() )
      dynamicPart += rowFmtStr
        .arg( TDEABC::Addressee::birthdayLabel() )
        .arg( TDEGlobal::locale()->formatDate( date, true ) );
  }

  if ( fieldMask & PhoneFields ) {
    TDEABC::PhoneNumber::List phones = addr.phoneNumbers();
    TDEABC::PhoneNumber::List::ConstIterator phoneIt;
    for ( phoneIt = phones.begin(); phoneIt != phones.end(); ++phoneIt ) {
      TQString number = TQStyleSheet::escape( (*phoneIt).number() );

      TQString url;
      if ( (*phoneIt).type() & TDEABC::PhoneNumber::Fax )
        url = TQString::fromLatin1( "fax:" ) + number;
      else
        url = TQString::fromLatin1( "phone:" ) + number;

      if ( linkMask & PhoneLinks ) {
        TQString smsURL;
        if ( (*phoneIt).type() & TDEABC::PhoneNumber::Cell )
          smsURL = TQString(" (<a href=\"sms:%1\">%2</a>)" ).arg( number ).arg( i18n( "SMS") );

        dynamicPart += rowFmtStr
          .arg( (*phoneIt).typeLabel().replace( " ", "&nbsp;" ) )
          .arg( TQString::fromLatin1( "<a href=\"%1\">%2</a>%3" ).arg( url ).arg( number ).arg( smsURL ) );
      } else {
        dynamicPart += rowFmtStr
          .arg( (*phoneIt).typeLabel().replace( " ", "&nbsp;" ) )
          .arg( number );
      }
    }
  }

  if ( fieldMask & EmailFields ) {
    TQStringList emails = addr.emails();
    TQStringList::ConstIterator emailIt;
    TQString type = i18n( "Email" );
    for ( emailIt = emails.begin(); emailIt != emails.end(); ++emailIt ) {
      TQString fullEmail = addr.fullEmail( *emailIt );
      TQUrl::encode( fullEmail );

      if ( linkMask & EmailLinks ) {
        dynamicPart += rowFmtStr.arg( type )
          .arg( TQString::fromLatin1( "<a href=\"mailto:%1\">%2</a>" )
          .arg( fullEmail, TQStyleSheet::escape( *emailIt ) ) );
      } else {
        dynamicPart += rowFmtStr.arg( type ).arg( *emailIt );
      }
    }
  }

  if ( fieldMask & URLFields ) {
    if ( !addr.url().url().isEmpty() ) {
      TQString url;
      if ( linkMask & URLLinks ) {
        url = (addr.url().url().startsWith( "http://" ) || addr.url().url().startsWith( "https://" ) ? addr.url().prettyURL() :
          "http://" + addr.url().prettyURL());
        url = KStringHandler::tagURLs( url );
      } else {
        url = addr.url().prettyURL();
      }
      dynamicPart += rowFmtStr.arg( i18n("Homepage") ).arg( url );
    }

    TQString blog = addr.custom( "KADDRESSBOOK", "BlogFeed" );
    if ( !blog.isEmpty() ) {
      if ( linkMask & URLLinks ) {
        blog = KStringHandler::tagURLs( blog );
      }
      dynamicPart += rowFmtStr.arg( i18n("Blog Feed") ).arg( blog );
    }
  }

  if ( fieldMask & AddressFields ) {
    TDEABC::Address::List addresses = addr.addresses();
    TDEABC::Address::List::ConstIterator addrIt;
    for ( addrIt = addresses.begin(); addrIt != addresses.end(); ++addrIt ) {
      if ( (*addrIt).label().isEmpty() ) {
        TQString formattedAddress;

        formattedAddress = TQStyleSheet::escape( (*addrIt).formattedAddress().stripWhiteSpace() );
        formattedAddress = formattedAddress.replace( '\n', "<br>" );

        TQString link = "<a href=\"addr:" + (*addrIt).id() + "\">" +
                       formattedAddress + "</a>";

        if ( linkMask & AddressLinks ) {
          dynamicPart += rowFmtStr
            .arg( TDEABC::Address::typeLabel( (*addrIt).type() ) )
            .arg( link );
        } else {
          dynamicPart += rowFmtStr
            .arg( TDEABC::Address::typeLabel( (*addrIt).type() ) )
            .arg( formattedAddress );
        }
      } else {
        TQString link = "<a href=\"addr:" + (*addrIt).id() + "\">" +
                       (*addrIt).label().replace( '\n', "<br>" ) + "</a>";

        if ( linkMask & AddressLinks ) {
          dynamicPart += rowFmtStr
            .arg( TDEABC::Address::typeLabel( (*addrIt).type() ) )
            .arg( link );
        } else {
          dynamicPart += rowFmtStr
            .arg( TDEABC::Address::typeLabel( (*addrIt).type() ) )
            .arg( (*addrIt).label().replace( '\n', "<br>" ) );
        }
      }
    }
  }

  TQString notes;
  if ( !addr.note().isEmpty() ) {
    // @STYLE@ - substitute the cell style in first, and append
    // the data afterwards (keeps us safe from possible % signs
    // in either one).
    notes = TQStyleSheet::escape( addr.note() );
    notes = rowFmtStr.arg( i18n( "Notes" ) ).arg( notes.replace( '\n', "<br>" ) ) ;
  }

  TQString customData;
  if ( fieldMask & CustomFields ) {
    static TQMap<TQString, TQString> titleMap;
    if ( titleMap.isEmpty() ) {
      titleMap.insert( "Department", i18n( "Department" ) );
      titleMap.insert( "Profession", i18n( "Profession" ) );
      titleMap.insert( "AssistantsName", i18n( "Assistant's Name" ) );
      titleMap.insert( "ManagersName", i18n( "Manager's Name" ) );
      titleMap.insert( "SpousesName", i18n( "Partner's Name" ) );
      titleMap.insert( "Office", i18n( "Office" ) );
      titleMap.insert( "Anniversary", i18n( "Anniversary" ) );
    }

    if ( !addr.customs().empty() ) {
      TQStringList customs = addr.customs();
      TQStringList::Iterator it( customs.begin() );
      const TQStringList::Iterator endIt( customs.end() );
      for ( ; it != endIt; ++it ) {
        TQString customEntry = *it;
        if ( customEntry.startsWith ( "KADDRESSBOOK-" ) ) {
          customEntry.remove( "KADDRESSBOOK-X-" );
          customEntry.remove( "KADDRESSBOOK-" );

          int pos = customEntry.find( ':' );
          TQString key = customEntry.left( pos );
          const TQString value = customEntry.mid( pos + 1 );

          // blog and im address is handled separated
          if ( key == "BlogFeed" || key == "IMAddress" )
            continue;

          const TQMap<TQString, TQString>::ConstIterator keyIt = titleMap.find( key );
          if ( keyIt != titleMap.end() )
            key = keyIt.data();

          customData += rowFmtStr.arg( key ).arg( TQStyleSheet::escape( value ) ) ;
        }
      }
    }
  }

  TQString name( TQStyleSheet::escape( addr.realName() ) );
  TQString role( TQStyleSheet::escape( addr.role() ) );
  TQString organization( TQStyleSheet::escape( addr.organization() ) );

  if ( fieldMask & IMFields ) {

    const TQString imAddress = addr.custom( "KADDRESSBOOK", "X-IMAddress" );
    if ( !imAddress.isEmpty() ) {
      customData += rowFmtStr.arg( i18n( "IM Address" ) ).arg( TQStyleSheet::escape( imAddress ) ) ;
    }

    if ( proxy ) {
      if ( proxy->isPresent( addr.uid() ) && proxy->presenceNumeric( addr.uid() ) > 0 ) {
        // set image source to either a TQMimeSourceFactory key or a data:/ URL
        TQString imgSrc;
        if ( internalLoading ) {
          imgSrc = TQString::fromLatin1( "im_status_%1_image").arg( addr.uid() );
          TQMimeSourceFactory::defaultFactory()->setPixmap( imgSrc, proxy->presenceIcon( addr.uid() ) );
        } else
          imgSrc = pixmapAsDataUrl( proxy->presenceIcon( addr.uid() ) );

        // make the status a link, if required
        TQString imStatus;
        if ( linkMask & IMLinks )
          imStatus = TQString::fromLatin1( "<a href=\"im:\"><img src=\"%1\"> (%2)</a>" );
        else
          imStatus = TQString::fromLatin1( "<img src=\"%1\"> (%2)" );

        // append our status to the rest of the dynamic part of the addressee
        dynamicPart += rowFmtStr
                .arg( i18n( "Presence" ) )
                .arg( imStatus
                          .arg( imgSrc )
                          .arg( proxy->presenceString( addr.uid() ) )
                    );
      }
    }
  }

  // @STYLE@ - construct the string by parts, substituting in
  // the styles first. There are lots of appends, but we need to
  // do it this way to avoid cases where the substituted string
  // contains %1 and the like.
  //
  TQString strAddr = TQString::fromLatin1(
    "<div align=\"center\">"
    "<table cellpadding=\"1\" cellspacing=\"0\" %1>"
    "<tr>").arg(tableStyle);

  strAddr.append( TQString::fromLatin1(
    "<td align=\"right\" valign=\"top\" width=\"30%\" rowspan=\"3\" %2>")
    .arg( cellStyle ) );
  strAddr.append( TQString::fromLatin1(
    "<img src=\"%1\" width=\"50\" vspace=\"1\">" // image
    "</td>")
    .arg( image ) );
  strAddr.append( TQString::fromLatin1(
    "<td align=\"left\" width=\"70%\" %2>")
    .arg( cellStyle2 ) );
  strAddr.append( TQString::fromLatin1(
    "<font size=\"+2\"><b>%2</b></font></td>"  // name
    "</tr>")
    .arg( name ) );
  strAddr.append( TQString::fromLatin1(
    "<tr>"
    "<td align=\"left\" width=\"70%\" %2>")
    .arg( cellStyle2 ) );
  strAddr.append( TQString::fromLatin1(
    "%3</td>"  // role
    "</tr>")
    .arg( role ) );
  strAddr.append( TQString::fromLatin1(
    "<tr>"
    "<td align=\"left\" width=\"70%\" %2>")
    .arg( cellStyle2 ) );
  strAddr.append( TQString::fromLatin1(
    "%4</td>"  // organization
    "</tr>")
    .arg( organization ) );
  strAddr.append( TQString::fromLatin1(
    "<tr><td %2>")
    .arg( cellStyle ) );
  strAddr.append( TQString::fromLatin1(
    "&nbsp;</td><td %2>&nbsp;</td></tr>")
    .arg( cellStyle2 ) );
  strAddr.append( dynamicPart );
  strAddr.append( notes );
  strAddr.append( customData );
  strAddr.append( TQString::fromLatin1( "</table></div>\n" ) );

  if ( addr.resource() ) {
    TQString addrBookName = addr.resource()->resourceName();
    ResourceABC *r = dynamic_cast<ResourceABC*>( addr.resource() );
    if ( r && !r->subresources().isEmpty() ) {
      const TQString subRes = r->uidToResourceMap()[ addr.uid() ];
      const TQString label = r->subresourceLabel( subRes );
      if ( !label.isEmpty() )
        addrBookName = label;
    }
    strAddr.append( i18n( "<p><b>Address book</b>: %1</p>" ).arg( addrBookName ) );
  }
  return strAddr;
}

TQString AddresseeView::pixmapAsDataUrl( const TQPixmap& pixmap )
{
  TQByteArray ba;
  TQBuffer buffer( ba );
  buffer.open( IO_WriteOnly );
  pixmap.save( &buffer, "PNG" );
  TQString encoded( "data:image/png;base64," );
  encoded.append( KCodecs::base64Encode( ba ) );
  return encoded;
}

void AddresseeView::updateView()
{
  // clear view
  setText( TQString() );

  if ( mAddressee.isEmpty() )
    return;

  if ( mImageJob ) {
    mImageJob->kill();
    mImageJob = 0;

    mImageData.truncate( 0 );
  }

  int fieldMask = NoFields;
  if ( mActionShowBirthday->isChecked() )
    fieldMask |= ( FieldMask )BirthdayFields;
  if ( mActionShowAddresses->isChecked() )
    fieldMask |= AddressFields;
  if ( mActionShowEmails->isChecked() )
    fieldMask |= EmailFields;
  if ( mActionShowPhones->isChecked() )
    fieldMask |= PhoneFields;
  if ( mActionShowURLs->isChecked() )
    fieldMask |= URLFields;
  if ( mActionShowIMAddresses->isChecked() )
    fieldMask |= IMFields;
  if ( mActionShowCustomFields->isChecked() )
    fieldMask |= CustomFields;

  TQString strAddr = vCardAsHTML( mAddressee, mKIMProxy, (LinkMask)mLinkMask,
                                 true, (FieldMask)fieldMask );

  strAddr = TQString::fromLatin1(
    "<html>"
    "<body text=\"%1\" bgcolor=\"%2\">" // text and background color
    "%3" // dynamic part
    "</body>"
    "</html>" )
     .arg( TDEGlobalSettings::textColor().name() )
     .arg( TDEGlobalSettings::baseColor().name() )
     .arg( strAddr );

  TQString imageURL = TQString( "contact_%1_image" ).arg( mAddressee.uid() );

  TDEABC::Picture picture = mAddressee.photo();
  if ( picture.isIntern() && !picture.data().isNull() )
    TQMimeSourceFactory::defaultFactory()->setImage( imageURL, picture.data() );
  else {
    if ( !picture.url().isEmpty() ) {
      if ( mImageData.count() > 0 )
        TQMimeSourceFactory::defaultFactory()->setImage( imageURL, TQImage(mImageData) );
      else {
        mImageJob = TDEIO::get( KURL( picture.url() ), false, false );
        connect( mImageJob, TQ_SIGNAL( data( TDEIO::Job*, const TQByteArray& ) ),
                 this, TQ_SLOT( data( TDEIO::Job*, const TQByteArray& ) ) );
        connect( mImageJob, TQ_SIGNAL( result( TDEIO::Job* ) ),
                 this, TQ_SLOT( result( TDEIO::Job* ) ) );
      }
    } else {
      TQMimeSourceFactory::defaultFactory()->setPixmap( imageURL,
        TDEGlobal::iconLoader()->loadIcon( "preferences-desktop-personal", TDEIcon::Desktop, 128 ) );
    }
  }

  // at last display it...
  setText( strAddr );
}

TDEABC::Addressee AddresseeView::addressee() const
{
  return mAddressee;
}

void AddresseeView::urlClicked( const TQString &url )
{
  tdeApp->invokeBrowser( url );
}

void AddresseeView::emailClicked( const TQString &email )
{
  if ( email.startsWith( "mailto:" ) )
    tdeApp->invokeMailer( email.mid( 7 ), TQString() );
  else
    tdeApp->invokeMailer( email, TQString() );
}

void AddresseeView::phoneNumberClicked( const TQString &number )
{
  TDEConfig config( "kaddressbookrc" );
  config.setGroup( "General" );
  TQString commandLine = config.readEntry( "PhoneHookApplication" );

  if ( commandLine.isEmpty() ) {
    KMessageBox::sorry( this, i18n( "There is no application set which could be executed. Please go to the settings dialog and configure one." ) );
    return;
  }

  commandLine.replace( "%N", number );
  KRun::runCommand( commandLine );
}

void AddresseeView::smsTextClicked( const TQString &number )
{
  TDEConfig config( "kaddressbookrc" );
  config.setGroup( "General" );
  TQString commandLine = config.readEntry( "SMSHookApplication" );

  if ( commandLine.isEmpty() ) {
    KMessageBox::sorry( this, i18n( "There is no application set which could be executed. Please go to the settings dialog and configure one." ) );
    return;
  }

  SendSMSDialog dlg( mAddressee.realName(), this );

  if ( dlg.exec() )
    sendSMS ( number, dlg.text() );
}

void AddresseeView::sendSMS( const TQString &number, const TQString &text )
{
  TDEConfig config( "kaddressbookrc" );
  config.setGroup( "General" );
  TQString commandLine = config.readEntry( "SMSHookApplication" );

  KTempFile file ;
  TQTextStream* stream = file.textStream();
  *stream << text;
  file.close();

  commandLine.replace( "%N", number );
  commandLine.replace( "%F", file.name() );

  KRun::runCommand( commandLine );
}

void AddresseeView::faxNumberClicked( const TQString &number )
{
  TDEConfig config( "kaddressbookrc" );
  config.setGroup( "General" );
  TQString commandLine = config.readEntry( "FaxHookApplication", "tdeprintfax --phone %N" );

  if ( commandLine.isEmpty() ) {
    KMessageBox::sorry( this, i18n( "There is no application set which could be executed. Please go to the settings dialog and configure one." ) );
    return;
  }

  commandLine.replace( "%N", number );
  KRun::runCommand( commandLine );
}

void AddresseeView::imAddressClicked()
{
  mKIMProxy->chatWithContact( mAddressee.uid() );
}

TQPopupMenu *AddresseeView::createPopupMenu( const TQPoint& )
{
  TQPopupMenu *menu = new TQPopupMenu( this );
  mActionShowBirthday->plug( menu );
  mActionShowAddresses->plug( menu );
  mActionShowEmails->plug( menu );
  mActionShowPhones->plug( menu );
  mActionShowURLs->plug( menu );
  mActionShowIMAddresses->plug( menu );
  mActionShowCustomFields->plug( menu );

  return menu;
}

void AddresseeView::slotMailClicked( const TQString&, const TQString &email )
{
  emailClicked( email );
}

void AddresseeView::slotUrlClicked( const TQString &url )
{
  if ( url.startsWith( "phone:" ) )
    phoneNumberClicked( strippedNumber( url.mid( 8 ) ) );
  else if ( url.startsWith( "sms:" ) )
    smsTextClicked( strippedNumber( url.mid( 6 ) ) );
  else if ( url.startsWith( "fax:" ) )
    faxNumberClicked( strippedNumber( url.mid( 6 ) ) );
  else if ( url.startsWith( "addr:" ) )
    emit addressClicked( url.mid( 7 ) );
  else if ( url.startsWith( "im:" ) )
    imAddressClicked();
  else
    urlClicked( url );
}

void AddresseeView::slotHighlighted( const TQString &link )
{
  if ( link.startsWith( "mailto:" ) ) {
    TQString email = link.mid( 7 );

    emit emailHighlighted( email );
    emit highlightedMessage( i18n( "Send mail to '%1'" ).arg( email ) );
  } else if ( link.startsWith( "phone:" ) ) {
    TQString number = link.mid( 8 );

    emit phoneNumberHighlighted( strippedNumber( number ) );
    emit highlightedMessage( i18n( "Call number %1" ).arg( number ) );
  } else if ( link.startsWith( "fax:" ) ) {
    TQString number = link.mid( 6 );

    emit faxNumberHighlighted( strippedNumber( number ) );
    emit highlightedMessage( i18n( "Send fax to %1" ).arg( number ) );
  } else if ( link.startsWith( "addr:" ) ) {
    emit highlightedMessage( i18n( "Show address on map" ) );
  } else if ( link.startsWith( "sms:" ) ) {
    TQString number = link.mid( 6 );
    emit highlightedMessage( i18n( "Send SMS to %1" ).arg( number ) );
  } else if ( link.startsWith( "http:" ) || link.startsWith( "https:" ) ) {
    emit urlHighlighted( link );
    emit highlightedMessage( i18n( "Open URL %1" ).arg( link ) );
  } else if ( link.startsWith( "im:" ) ) {
    emit highlightedMessage( i18n( "Chat with %1" ).arg( mAddressee.realName() ) );
  } else
    emit highlightedMessage( "" );
}

void AddresseeView::slotPresenceChanged( const TQString &uid )
{
  kdDebug() << k_funcinfo << " uid is: " << uid << " mAddressee is: " << mAddressee.uid() << endl;
  if ( uid == mAddressee.uid() )
    updateView();
}


void AddresseeView::slotPresenceInfoExpired()
{
  updateView();
}

void AddresseeView::configChanged()
{
  save();
  updateView();
}

void AddresseeView::data( TDEIO::Job*, const TQByteArray &d )
{
  unsigned int oldSize = mImageData.size();
  mImageData.resize( oldSize + d.size() );
  memcpy( mImageData.data() + oldSize, d.data(), d.size() );
}

void AddresseeView::result( TDEIO::Job *job )
{
  mImageJob = 0;

  if ( job->error() )
    mImageData.truncate( 0 );
  else
    updateView();
}

void AddresseeView::load()
{
  mConfig->setGroup( "AddresseeViewSettings" );
  mActionShowBirthday->setChecked( mConfig->readBoolEntry( "ShowBirthday", false ) );
  mActionShowAddresses->setChecked( mConfig->readBoolEntry( "ShowAddresses", true ) );
  mActionShowEmails->setChecked( mConfig->readBoolEntry( "ShowEmails", true ) );
  mActionShowPhones->setChecked( mConfig->readBoolEntry( "ShowPhones", true ) );
  mActionShowURLs->setChecked( mConfig->readBoolEntry( "ShowURLs", true ) );
  mActionShowIMAddresses->setChecked( mConfig->readBoolEntry( "ShowIMAddresses", false ) );
  mActionShowCustomFields->setChecked( mConfig->readBoolEntry( "ShowCustomFields", false ) );
}

void AddresseeView::save()
{
  mConfig->setGroup( "AddresseeViewSettings" );
  mConfig->writeEntry( "ShowBirthday", mActionShowBirthday->isChecked() );
  mConfig->writeEntry( "ShowAddresses", mActionShowAddresses->isChecked() );
  mConfig->writeEntry( "ShowEmails", mActionShowEmails->isChecked() );
  mConfig->writeEntry( "ShowPhones", mActionShowPhones->isChecked() );
  mConfig->writeEntry( "ShowURLs", mActionShowURLs->isChecked() );
  mConfig->writeEntry( "ShowIMAddresses", mActionShowIMAddresses->isChecked() );
  mConfig->writeEntry( "ShowCustomFields", mActionShowCustomFields->isChecked() );
  mConfig->sync();
}

TQString AddresseeView::strippedNumber( const TQString &number )
{
  TQString retval;

  for ( uint i = 0; i < number.length(); ++i ) {
    TQChar c = number[ i ];
    if ( c.isDigit() || (((c == '*') || (c == '#') || (c == '+')) && (i == 0)) )
      retval.append( c );
  }

  return retval;
}

#include "addresseeview.moc"
