// kaddrbook.cpp
// Author: Stefan Taferner <taferner@kde.org>
// This code is under GPL

#include <config.h>

#include "kaddrbook.h"

#ifdef TDEPIM_NEW_DISTRLISTS
#include "distributionlist.h"
#else
#include <tdeabc/distributionlist.h>
#endif

#include <tdeapplication.h>
#include <kdebug.h>
#include <tdelocale.h>
#include <tdemessagebox.h>
#include <tdeversion.h>
#include <tdeabc/resource.h>
#include <tdeabc/stdaddressbook.h>
#include <tdeabc/vcardconverter.h>
#include <tdeabc/errorhandler.h>
#include <tderesources/selectdialog.h>
#include <dcopref.h>
#include <dcopclient.h>

#include <tqeventloop.h>
#include <tqregexp.h>

#include <unistd.h>

//-----------------------------------------------------------------------------
void KAddrBookExternal::openEmail( const TQString &addr, TQWidget *parent ) {
  TQString email;
  TQString name;

  TDEABC::Addressee::parseEmailAddress( addr, name, email );

  TDEABC::AddressBook *ab = TDEABC::StdAddressBook::self( true );

  // force a reload of the address book file so that changes that were made
  // by other programs are loaded
  ab->asyncLoad();

  // if we have to reload the address book then we should also wait until
  // it's completely reloaded
#if KDE_IS_VERSION(3,4,89)
  // This ugly hack will be removed in 4.0
  while ( !ab->loadingHasFinished() ) {
    TQApplication::eventLoop()->processEvents( TQEventLoop::ExcludeUserInput );

    // use sleep here to reduce cpu usage
    usleep( 100 );
  }
#endif

  TDEABC::Addressee::List addressees = ab->findByEmail( email );

  if ( addressees.count() > 0 ) {
    if ( tdeApp->dcopClient()->isApplicationRegistered( "kaddressbook" ) ){
      //make sure kaddressbook is loaded, otherwise showContactEditor
      //won't work as desired, see bug #87233
      DCOPRef call ( "kaddressbook", "kaddressbook" );
      call.send( "newInstance()" );
    }  else {
      tdeApp->startServiceByDesktopName( "kaddressbook" );
    }

    DCOPRef call( "kaddressbook", "KAddressBookIface" );
    call.send( "showContactEditor(TQString)", addressees.first().uid() );
  } else {
    //TODO: Enable the better message at the next string unfreeze
#if 0
    TQString text = i18n("<qt>The email address <b>%1</b> cannot be "
                        "found in your addressbook.</qt>").arg( email );
#else
    TQString text = email + " " + i18n( "is not in address book" );
#endif
    KMessageBox::information( parent, text, TQString(), "notInAddressBook" );
  }
}

//-----------------------------------------------------------------------------
void KAddrBookExternal::addEmail( const TQString& addr, TQWidget *parent) {
  TQString email;
  TQString name;

  TDEABC::Addressee::parseEmailAddress( addr, name, email );

  TDEABC::AddressBook *ab = TDEABC::StdAddressBook::self( true );

  ab->setErrorHandler( new TDEABC::GuiErrorHandler( parent ) );

  // force a reload of the address book file so that changes that were made
  // by other programs are loaded
  ab->asyncLoad();

  // if we have to reload the address book then we should also wait until
  // it's completely reloaded
#if KDE_IS_VERSION(3,4,89)
  // This ugly hack will be removed in 4.0
  while ( !ab->loadingHasFinished() ) {
    TQApplication::eventLoop()->processEvents( TQEventLoop::ExcludeUserInput );

    // use sleep here to reduce cpu usage
    usleep( 100 );
  }
#endif

  TDEABC::Addressee::List addressees = ab->findByEmail( email );

  if ( addressees.isEmpty() ) {
    TDEABC::Addressee a;
    a.setNameFromString( name );
    a.insertEmail( email, true );

    {
      TDEConfig config( "kaddressbookrc" );
      config.setGroup( "General" );
      int type = config.readNumEntry( "FormattedNameType", 1 );

      TQString name;
      switch ( type ) {
        case 1:
          name = a.givenName() + " " + a.familyName();
          break;
        case 2:
          name = a.assembledName();
          break;
        case 3:
          name = a.familyName() + ", " + a.givenName();
          break;
        case 4:
          name = a.familyName() + " " + a.givenName();
          break;
        case 5:
          name = a.organization();
          break;
        default:
          name = "";
          break;
      }
      name.simplifyWhiteSpace();

      a.setFormattedName( name );
    }

    if ( KAddrBookExternal::addAddressee( a ) ) {
      TQString text = i18n("<qt>The email address <b>%1</b> was added to your "
                          "addressbook; you can add more information to this "
                          "entry by opening the addressbook.</qt>").arg( addr );
      KMessageBox::information( parent, text, TQString(), "addedtokabc" );
    }
  } else {
    TQString text = i18n("<qt>The email address <b>%1</b> is already in your "
                        "addressbook.</qt>").arg( addr );
    KMessageBox::information( parent, text, TQString(),
                              "alreadyInAddressBook" );
  }
  ab->setErrorHandler( 0 );
}

void KAddrBookExternal::openAddressBook(TQWidget *) {
  tdeApp->startServiceByDesktopName( "kaddressbook" );
}

void KAddrBookExternal::addNewAddressee( TQWidget* )
{
  tdeApp->startServiceByDesktopName("kaddressbook");
  DCOPRef call("kaddressbook", "KAddressBookIface");
  call.send("newContact()");
}

bool KAddrBookExternal::addVCard( const TDEABC::Addressee& addressee, TQWidget *parent )
{
  TDEABC::AddressBook *ab = TDEABC::StdAddressBook::self( true );
  bool inserted = false;

  ab->setErrorHandler( new TDEABC::GuiErrorHandler( parent ) );

  TDEABC::Addressee::List addressees =
      ab->findByEmail( addressee.preferredEmail() );

  if ( addressees.isEmpty() ) {
    if ( KAddrBookExternal::addAddressee( addressee ) ) {
      TQString text = i18n("The VCard was added to your addressbook; "
                          "you can add more information to this "
                          "entry by opening the addressbook.");
      KMessageBox::information( parent, text, TQString(), "addedtokabc" );
      inserted = true;
    }
  } else {
    TQString text = i18n("The VCard's primary email address is already in "
                        "your addressbook; however, you may save the VCard "
                        "into a file and import it into the addressbook "
                        "manually.");
    KMessageBox::information( parent, text );
    inserted = true;
  }

  ab->setErrorHandler( 0 );
  return inserted;
}

bool KAddrBookExternal::addAddressee( const TDEABC::Addressee& addr )
{
  TDEABC::AddressBook *addressBook = TDEABC::StdAddressBook::self( true );
  TDEABC::Resource *tdeabcResource = selectResourceForSaving( addressBook );
  if( !tdeabcResource ) 
     return false;
  TDEABC::Ticket *ticket = addressBook->requestSaveTicket( tdeabcResource );
  bool saved = false;
  if ( ticket ) {
    TDEABC::Addressee addressee( addr );
    addressee.setResource( tdeabcResource );
    addressBook->insertAddressee( addressee );
    saved = addressBook->save( ticket );
    if ( !saved )
      addressBook->releaseSaveTicket( ticket );
  }

  addressBook->emitAddressBookChanged();

  return saved;
}

TQString KAddrBookExternal::expandDistributionList( const TQString& listName )
{
  if ( listName.isEmpty() )
    return TQString();

  const TQString lowerListName = listName.lower();
  TDEABC::AddressBook *addressBook = TDEABC::StdAddressBook::self( true );
#ifdef TDEPIM_NEW_DISTRLISTS
  KPIM::DistributionList distrList = KPIM::DistributionList::findByName( addressBook, lowerListName, false );
  if ( !distrList.isEmpty() ) {
    return distrList.emails( addressBook ).join( ", " );
  }
#else
  TDEABC::DistributionListManager manager( addressBook );
  manager.load();
  const TQStringList listNames = manager.listNames();

  for ( TQStringList::ConstIterator it = listNames.begin();
        it != listNames.end(); ++it) {
    if ( (*it).lower() == lowerListName ) {
      const TQStringList addressList = manager.list( *it )->emails();
      return addressList.join( ", " );
    }
  }
#endif
  return TQString();
}

TDEABC::Resource* KAddrBookExternal::selectResourceForSaving( TDEABC::AddressBook *addressBook )
{
#if KDE_IS_VERSION(3,4,89)
  // This ugly hack will be removed in 4.0
  while ( !addressBook->loadingHasFinished() ) {
    TQApplication::eventLoop()->processEvents( TQEventLoop::ExcludeUserInput );

    // use sleep here to reduce cpu usage
    usleep( 100 );
  }
#endif

  // Select a resource
  TQPtrList<TDEABC::Resource> tdeabcResources = addressBook->resources();

  TQPtrList<KRES::Resource> kresResources;
  TQPtrListIterator<TDEABC::Resource> resIt( tdeabcResources );
  TDEABC::Resource *tdeabcResource;
  while ( ( tdeabcResource = resIt.current() ) != 0 ) {
    ++resIt;
    if ( !tdeabcResource->readOnly() ) {
      KRES::Resource *res = static_cast<KRES::Resource*>( tdeabcResource );
      if ( res )
        kresResources.append( res );
    }
  }

  return static_cast<TDEABC::Resource*>( KRES::SelectDialog::getResource( kresResources, 0 ) );
}