/*** Warning! This file has been generated by the script makeaddressee ***/
/*
    This file is part of libkabc.
    Copyright (c) 2002 Cornelius Schumacher <schumacher@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 <klocale.h>
#include <kconfig.h>
#include <kglobal.h>

#include "field.h"
#include "address.h"

using namespace KABC;

class Field::FieldImpl
{
  public:
    FieldImpl( int fieldId, int category = 0,
               const QString &label = QString::null,
               const QString &key = QString::null,
               const QString &app = QString::null )
      : mFieldId( fieldId ), mCategory( category ), mLabel( label ),
        mKey( key ), mApp( app ) {}

    enum FieldId
    {
      CustomField,
      FormattedName,
      FamilyName,
      GivenName,
      AdditionalName,
      Prefix,
      Suffix,
      NickName,
      Birthday,
      HomeAddressStreet,
      HomeAddressPostOfficeBox,
      HomeAddressLocality,
      HomeAddressRegion,
      HomeAddressPostalCode,
      HomeAddressCountry,
      HomeAddressLabel,
      BusinessAddressStreet,
      BusinessAddressPostOfficeBox,
      BusinessAddressLocality,
      BusinessAddressRegion,
      BusinessAddressPostalCode,
      BusinessAddressCountry,
      BusinessAddressLabel,
      HomePhone,
      BusinessPhone,
      MobilePhone,
      HomeFax,
      BusinessFax,
      CarPhone,
      Isdn,
      Pager,
      Email,
      Mailer,
      Title,
      Role,
      Organization,
      Department,
      Note,
      Url
    };

    int fieldId() { return mFieldId; }
    int category() { return mCategory; }

    QString label() { return mLabel; }
    QString key() { return mKey; }
    QString app() { return mApp; }

  private:
    int mFieldId;
    int mCategory;

    QString mLabel;
    QString mKey;
    QString mApp;
};


Field::List Field::mAllFields;
Field::List Field::mDefaultFields;
Field::List Field::mCustomFields;


Field::Field( FieldImpl *impl )
{
  mImpl = impl;
}

Field::~Field()
{
  delete mImpl;
}

QString Field::label()
{
  switch ( mImpl->fieldId() ) {
    case FieldImpl::FormattedName:
      return Addressee::formattedNameLabel();
    case FieldImpl::FamilyName:
      return Addressee::familyNameLabel();
    case FieldImpl::GivenName:
      return Addressee::givenNameLabel();
    case FieldImpl::AdditionalName:
      return Addressee::additionalNameLabel();
    case FieldImpl::Prefix:
      return Addressee::prefixLabel();
    case FieldImpl::Suffix:
      return Addressee::suffixLabel();
    case FieldImpl::NickName:
      return Addressee::nickNameLabel();
    case FieldImpl::Birthday:
      return Addressee::birthdayLabel();
    case FieldImpl::HomeAddressStreet:
      return Addressee::homeAddressStreetLabel();
    case FieldImpl::HomeAddressPostOfficeBox:
      return Addressee::homeAddressPostOfficeBoxLabel();
    case FieldImpl::HomeAddressLocality:
      return Addressee::homeAddressLocalityLabel();
    case FieldImpl::HomeAddressRegion:
      return Addressee::homeAddressRegionLabel();
    case FieldImpl::HomeAddressPostalCode:
      return Addressee::homeAddressPostalCodeLabel();
    case FieldImpl::HomeAddressCountry:
      return Addressee::homeAddressCountryLabel();
    case FieldImpl::HomeAddressLabel:
      return Addressee::homeAddressLabelLabel();
    case FieldImpl::BusinessAddressStreet:
      return Addressee::businessAddressStreetLabel();
    case FieldImpl::BusinessAddressPostOfficeBox:
      return Addressee::businessAddressPostOfficeBoxLabel();
    case FieldImpl::BusinessAddressLocality:
      return Addressee::businessAddressLocalityLabel();
    case FieldImpl::BusinessAddressRegion:
      return Addressee::businessAddressRegionLabel();
    case FieldImpl::BusinessAddressPostalCode:
      return Addressee::businessAddressPostalCodeLabel();
    case FieldImpl::BusinessAddressCountry:
      return Addressee::businessAddressCountryLabel();
    case FieldImpl::BusinessAddressLabel:
      return Addressee::businessAddressLabelLabel();
    case FieldImpl::HomePhone:
      return Addressee::homePhoneLabel();
    case FieldImpl::BusinessPhone:
      return Addressee::businessPhoneLabel();
    case FieldImpl::MobilePhone:
      return Addressee::mobilePhoneLabel();
    case FieldImpl::HomeFax:
      return Addressee::homeFaxLabel();
    case FieldImpl::BusinessFax:
      return Addressee::businessFaxLabel();
    case FieldImpl::CarPhone:
      return Addressee::carPhoneLabel();
    case FieldImpl::Isdn:
      return Addressee::isdnLabel();
    case FieldImpl::Pager:
      return Addressee::pagerLabel();
    case FieldImpl::Email:
      return Addressee::emailLabel();
    case FieldImpl::Mailer:
      return Addressee::mailerLabel();
    case FieldImpl::Title:
      return Addressee::titleLabel();
    case FieldImpl::Role:
      return Addressee::roleLabel();
    case FieldImpl::Organization:
      return Addressee::organizationLabel();
    case FieldImpl::Department:
      return Addressee::departmentLabel();
    case FieldImpl::Note:
      return Addressee::noteLabel();
    case FieldImpl::Url:
      return Addressee::urlLabel();
    case FieldImpl::CustomField:
      return mImpl->label();
    default:
      return i18n("Unknown Field");
  }
}

int Field::category()
{
  return mImpl->category();
}

QString Field::categoryLabel( int category )
{
  switch ( category ) {
    case All:
      return i18n("All");
    case Frequent:
      return i18n("Frequent");
    case Address:
      return i18n("street/postal","Address");
    case Email:
      return i18n("Email");
    case Personal:
      return i18n("Personal");
    case Organization:
      return i18n("Organization");
    case CustomCategory:
      return i18n("Custom");
    default:
      return i18n("Undefined");
  }
}

QString Field::value( const KABC::Addressee &a )
{
  switch ( mImpl->fieldId() ) {
    case FieldImpl::FormattedName:
      return a.formattedName();
    case FieldImpl::FamilyName:
      return a.familyName();
    case FieldImpl::GivenName:
      return a.givenName();
    case FieldImpl::AdditionalName:
      return a.additionalName();
    case FieldImpl::Prefix:
      return a.prefix();
    case FieldImpl::Suffix:
      return a.suffix();
    case FieldImpl::NickName:
      return a.nickName();
    case FieldImpl::Mailer:
      return a.mailer();
    case FieldImpl::Title:
      return a.title();
    case FieldImpl::Role:
      return a.role();
    case FieldImpl::Organization:
      return a.organization();
    case FieldImpl::Department:
      return a.department();
    case FieldImpl::Note:
      return a.note();
    case FieldImpl::Email:
      return a.preferredEmail();
    case FieldImpl::Birthday:
      if ( a.birthday().isValid() )
        return a.birthday().date().toString( Qt::ISODate );
      else
        return QString::null;
    case FieldImpl::Url:
      return a.url().prettyURL();
    case FieldImpl::HomePhone:
    {
      PhoneNumber::List::ConstIterator it;

      {
        // check for preferred number
        const PhoneNumber::List list = a.phoneNumbers( PhoneNumber::Home | PhoneNumber::Pref );
        for ( it = list.begin(); it != list.end(); ++it )
          if ( ((*it).type() & ~(PhoneNumber::Pref)) == PhoneNumber::Home )
            return (*it).number();
      }

      {
        // check for normal home number
        const PhoneNumber::List list = a.phoneNumbers( PhoneNumber::Home );
        for ( it = list.begin(); it != list.end(); ++it )
          if ( ((*it).type() & ~(PhoneNumber::Pref)) == PhoneNumber::Home )
            return (*it).number();
      }

      return QString::null;
    }
    case FieldImpl::BusinessPhone:
    {
      PhoneNumber::List::ConstIterator it;

      {
        // check for preferred number
        const PhoneNumber::List list = a.phoneNumbers( PhoneNumber::Work | PhoneNumber::Pref );
        for ( it = list.begin(); it != list.end(); ++it )
          if ( ((*it).type() & ~(PhoneNumber::Pref)) == PhoneNumber::Work )
            return (*it).number();
      }

      {
        // check for normal work number
        const PhoneNumber::List list = a.phoneNumbers( PhoneNumber::Work );
        for ( it = list.begin(); it != list.end(); ++it )
          if ( ((*it).type() & ~(PhoneNumber::Pref)) == PhoneNumber::Work )
            return (*it).number();
      }

      return QString::null;
    }
    case FieldImpl::MobilePhone:
      return a.phoneNumber( PhoneNumber::Cell ).number();
    case FieldImpl::HomeFax:
      return a.phoneNumber( PhoneNumber::Home | PhoneNumber::Fax ).number();
    case FieldImpl::BusinessFax:
      return a.phoneNumber( PhoneNumber::Work | PhoneNumber::Fax ).number();
    case FieldImpl::CarPhone:
      return a.phoneNumber( PhoneNumber::Car ).number();
    case FieldImpl::Isdn:
      return a.phoneNumber( PhoneNumber::Isdn ).number();
    case FieldImpl::Pager:
      return a.phoneNumber( PhoneNumber::Pager ).number();
    case FieldImpl::HomeAddressStreet:
      return a.address( Address::Home ).street();
    case FieldImpl::HomeAddressPostOfficeBox:
      return a.address( Address::Home ).postOfficeBox();
    case FieldImpl::HomeAddressLocality:
      return a.address( Address::Home ).locality();
    case FieldImpl::HomeAddressRegion:
      return a.address( Address::Home ).region();
    case FieldImpl::HomeAddressPostalCode:
      return a.address( Address::Home ).postalCode();
    case FieldImpl::HomeAddressCountry:
      return a.address( Address::Home ).country();
    case FieldImpl::HomeAddressLabel:
      return a.address( Address::Home ).label();
    case FieldImpl::BusinessAddressStreet:
      return a.address( Address::Work ).street();
    case FieldImpl::BusinessAddressPostOfficeBox:
      return a.address( Address::Work ).postOfficeBox();
    case FieldImpl::BusinessAddressLocality:
      return a.address( Address::Work ).locality();
    case FieldImpl::BusinessAddressRegion:
      return a.address( Address::Work ).region();
    case FieldImpl::BusinessAddressPostalCode:
      return a.address( Address::Work ).postalCode();
    case FieldImpl::BusinessAddressCountry:
      return a.address( Address::Work ).country();
    case FieldImpl::BusinessAddressLabel:
      return a.address( Address::Work ).label();
    case FieldImpl::CustomField:
      return a.custom( mImpl->app(), mImpl->key() );
    default:
      return QString::null;
  }
}

bool Field::setValue( KABC::Addressee &a, const QString &value )
{
  switch ( mImpl->fieldId() ) {
    case FieldImpl::FormattedName:
      a.setFormattedName( value );
      return true;
    case FieldImpl::FamilyName:
      a.setFamilyName( value );
      return true;
    case FieldImpl::GivenName:
      a.setGivenName( value );
      return true;
    case FieldImpl::AdditionalName:
      a.setAdditionalName( value );
      return true;
    case FieldImpl::Prefix:
      a.setPrefix( value );
      return true;
    case FieldImpl::Suffix:
      a.setSuffix( value );
      return true;
    case FieldImpl::NickName:
      a.setNickName( value );
      return true;
    case FieldImpl::Mailer:
      a.setMailer( value );
      return true;
    case FieldImpl::Title:
      a.setTitle( value );
      return true;
    case FieldImpl::Role:
      a.setRole( value );
      return true;
    case FieldImpl::Organization:
      a.setOrganization( value );
      return true;
    case FieldImpl::Department:
      a.setDepartment( value );
      return true;
    case FieldImpl::Note:
      a.setNote( value );
      return true;
    case FieldImpl::MobilePhone:
      {
        PhoneNumber number = a.phoneNumber( PhoneNumber::Cell );
        number.setNumber( value );
        a.insertPhoneNumber( number );
        return true;
      }
    case FieldImpl::HomeFax:
      {
        PhoneNumber number = a.phoneNumber( PhoneNumber::Home | PhoneNumber::Fax );
        number.setNumber( value );
        a.insertPhoneNumber( number );
        return true;
      }
    case FieldImpl::BusinessFax:
      {
        PhoneNumber number = a.phoneNumber( PhoneNumber::Work | PhoneNumber::Fax );
        number.setNumber( value );
        a.insertPhoneNumber( number );
        return true;
      }
    case FieldImpl::CarPhone:
      {
        PhoneNumber number = a.phoneNumber( PhoneNumber::Car );
        number.setNumber( value );
        a.insertPhoneNumber( number );
        return true;
      }
    case FieldImpl::Isdn:
      {
        PhoneNumber number = a.phoneNumber( PhoneNumber::Isdn );
        number.setNumber( value );
        a.insertPhoneNumber( number );
        return true;
      }
    case FieldImpl::Pager:
      {
        PhoneNumber number = a.phoneNumber( PhoneNumber::Pager );
        number.setNumber( value );
        a.insertPhoneNumber( number );
        return true;
      }
    case FieldImpl::HomeAddressStreet:
      {
        KABC::Address address = a.address( Address::Home );
        address.setStreet( value );
        a.insertAddress( address );
        return true;
      }
    case FieldImpl::HomeAddressPostOfficeBox:
      {
        KABC::Address address = a.address( Address::Home );
        address.setPostOfficeBox( value );
        a.insertAddress( address );
        return true;
      }
    case FieldImpl::HomeAddressLocality:
      {
        KABC::Address address = a.address( Address::Home );
        address.setLocality( value );
        a.insertAddress( address );
        return true;
      }
    case FieldImpl::HomeAddressRegion:
      {
        KABC::Address address = a.address( Address::Home );
        address.setRegion( value );
        a.insertAddress( address );
        return true;
      }
    case FieldImpl::HomeAddressPostalCode:
      {
        KABC::Address address = a.address( Address::Home );
        address.setPostalCode( value );
        a.insertAddress( address );
        return true;
      }
    case FieldImpl::HomeAddressCountry:
      {
        KABC::Address address = a.address( Address::Home );
        address.setCountry( value );
        a.insertAddress( address );
        return true;
      }
    case FieldImpl::HomeAddressLabel:
      {
        KABC::Address address = a.address( Address::Home );
        address.setLabel( value );
        a.insertAddress( address );
        return true;
      }
    case FieldImpl::BusinessAddressStreet:
      {
        KABC::Address address = a.address( Address::Work );
        address.setStreet( value );
        a.insertAddress( address );
        return true;
      }
    case FieldImpl::BusinessAddressPostOfficeBox:
      {
        KABC::Address address = a.address( Address::Work );
        address.setPostOfficeBox( value );
        a.insertAddress( address );
        return true;
      }
    case FieldImpl::BusinessAddressLocality:
      {
        KABC::Address address = a.address( Address::Work );
        address.setLocality( value );
        a.insertAddress( address );
        return true;
      }
    case FieldImpl::BusinessAddressRegion:
      {
        KABC::Address address = a.address( Address::Work );
        address.setRegion( value );
        a.insertAddress( address );
        return true;
      }
    case FieldImpl::BusinessAddressPostalCode:
      {
        KABC::Address address = a.address( Address::Work );
        address.setPostalCode( value );
        a.insertAddress( address );
        return true;
      }
    case FieldImpl::BusinessAddressCountry:
      {
        KABC::Address address = a.address( Address::Work );
        address.setCountry( value );
        a.insertAddress( address );
        return true;
      }
    case FieldImpl::BusinessAddressLabel:
      {
        KABC::Address address = a.address( Address::Work );
        address.setLabel( value );
        a.insertAddress( address );
        return true;
      }
    case FieldImpl::Birthday:
      a.setBirthday( QDate::fromString( value, Qt::ISODate ) );
      return true;
    case FieldImpl::CustomField:
      a.insertCustom( mImpl->app(), mImpl->key(), value );
      return true;
    default:
      return false;
  }
}

QString Field::sortKey( const KABC::Addressee &a )
{
  switch ( mImpl->fieldId() ) {
    case FieldImpl::FormattedName:
      return a.formattedName();
    case FieldImpl::FamilyName:
      return a.familyName();
    case FieldImpl::GivenName:
      return a.givenName();
    case FieldImpl::AdditionalName:
      return a.additionalName();
    case FieldImpl::Prefix:
      return a.prefix();
    case FieldImpl::Suffix:
      return a.suffix();
    case FieldImpl::NickName:
      return a.nickName();
    case FieldImpl::Mailer:
      return a.mailer();
    case FieldImpl::Title:
      return a.title();
    case FieldImpl::Role:
      return a.role();
    case FieldImpl::Organization:
      return a.organization();
    case FieldImpl::Department:
      return a.department();
    case FieldImpl::Note:
      return a.note();
    case FieldImpl::Birthday:
      if ( a.birthday().isValid() ) {
        QDate date = a.birthday().date();
        QString key;
        key.sprintf( "%02d-%02d", date.month(), date.day() );
        return key;
      } else
        return QString( "00-00" );
    default:
      return value( a ).lower();
  }
}

bool Field::isCustom()
{
  return mImpl->fieldId() == FieldImpl::CustomField;
}

Field::List Field::allFields()
{
  if ( mAllFields.isEmpty() ) {
    createField( FieldImpl::FormattedName, Frequent );
    createField( FieldImpl::FamilyName, Frequent );
    createField( FieldImpl::GivenName, Frequent );
    createField( FieldImpl::AdditionalName );
    createField( FieldImpl::Prefix );
    createField( FieldImpl::Suffix );
    createField( FieldImpl::NickName, Personal );
    createField( FieldImpl::Birthday, Personal );
    createField( FieldImpl::HomeAddressStreet, Address|Personal );
    createField( FieldImpl::HomeAddressPostOfficeBox, Address|Personal );
    createField( FieldImpl::HomeAddressLocality, Address|Personal );
    createField( FieldImpl::HomeAddressRegion, Address|Personal );
    createField( FieldImpl::HomeAddressPostalCode, Address|Personal );
    createField( FieldImpl::HomeAddressCountry, Address|Personal );
    createField( FieldImpl::HomeAddressLabel, Address|Personal );
    createField( FieldImpl::BusinessAddressStreet, Address|Organization );
    createField( FieldImpl::BusinessAddressPostOfficeBox, Address|Organization );
    createField( FieldImpl::BusinessAddressLocality, Address|Organization );
    createField( FieldImpl::BusinessAddressRegion, Address|Organization );
    createField( FieldImpl::BusinessAddressPostalCode, Address|Organization );
    createField( FieldImpl::BusinessAddressCountry, Address|Organization );
    createField( FieldImpl::BusinessAddressLabel, Address|Organization );
    createField( FieldImpl::HomePhone, Personal|Frequent );
    createField( FieldImpl::BusinessPhone, Organization|Frequent );
    createField( FieldImpl::MobilePhone, Frequent );
    createField( FieldImpl::HomeFax );
    createField( FieldImpl::BusinessFax );
    createField( FieldImpl::CarPhone );
    createField( FieldImpl::Isdn );
    createField( FieldImpl::Pager );
    createField( FieldImpl::Email, Email|Frequent );
    createField( FieldImpl::Mailer, Email );
    createField( FieldImpl::Title, Organization );
    createField( FieldImpl::Role, Organization );
    createField( FieldImpl::Organization, Organization );
    createField( FieldImpl::Department, Organization );
    createField( FieldImpl::Note );
    createField( FieldImpl::Url );
  }

  return mAllFields;
}

Field::List Field::defaultFields()
{
  if ( mDefaultFields.isEmpty() ) {
    createDefaultField( FieldImpl::FormattedName );
    createDefaultField( FieldImpl::Email );
  }

  return mDefaultFields;
}

void Field::createField( int id, int category )
{
  mAllFields.append( new Field( new FieldImpl( id, category ) ) );
}

void Field::createDefaultField( int id, int category )
{
  mDefaultFields.append( new Field( new FieldImpl( id, category ) ) );
}

void Field::deleteFields()
{
  Field::List::ConstIterator it;

  for ( it = mAllFields.constBegin(); it != mAllFields.constEnd(); ++it ) {
    delete (*it);
  }
  mAllFields.clear();

  for ( it = mDefaultFields.constBegin(); it != mDefaultFields.constEnd(); ++it ) {
    delete (*it);
  }
  mDefaultFields.clear();

  for ( it = mCustomFields.constBegin(); it != mCustomFields.constEnd(); ++it ) {
    delete (*it);
  }
  mCustomFields.clear();
}

void Field::saveFields( const QString &identifier,
                        const Field::List &fields )
{
  KConfig *cfg = KGlobal::config();
  KConfigGroupSaver( cfg, "KABCFields" );

  saveFields( cfg, identifier, fields );
}

void Field::saveFields( KConfig *cfg, const QString &identifier,
                        const Field::List &fields )
{
  QValueList<int> fieldIds;

  int custom = 0;
  Field::List::ConstIterator it;
  for( it = fields.begin(); it != fields.end(); ++it ) {
    fieldIds.append( (*it)->mImpl->fieldId() );
    if( (*it)->isCustom() ) {
      QStringList customEntry;
      customEntry << (*it)->mImpl->label();
      customEntry << (*it)->mImpl->key();
      customEntry << (*it)->mImpl->app();
      cfg->writeEntry( "KABC_CustomEntry_" + identifier + "_" +
                       QString::number( custom++ ), customEntry );
    }
  }

  cfg->writeEntry( identifier, fieldIds );
}

Field::List Field::restoreFields( const QString &identifier )
{
  KConfig *cfg = KGlobal::config();
  KConfigGroupSaver( cfg, "KABCFields" );

  return restoreFields( cfg, identifier );
}

Field::List Field::restoreFields( KConfig *cfg, const QString &identifier )
{
  const QValueList<int> fieldIds = cfg->readIntListEntry( identifier );

  Field::List fields;

  int custom = 0;
  QValueList<int>::ConstIterator it;
  for( it = fieldIds.begin(); it != fieldIds.end(); ++it ) {
    FieldImpl *f = 0;
    if ( (*it) == FieldImpl::CustomField ) {
      QStringList customEntry = cfg->readListEntry( "KABC_CustomEntry_" +
                                                 identifier + "_" +
                                                 QString::number( custom++ ) );
      f = new FieldImpl( *it, CustomCategory, customEntry[ 0 ],
                         customEntry[ 1 ], customEntry[ 2 ] );
    } else {
      f = new FieldImpl( *it );
    }
    fields.append( new Field( f ) );
  }

  return fields;
}

bool Field::equals( Field *field )
{
  bool sameId = ( mImpl->fieldId() == field->mImpl->fieldId() );

  if ( !sameId ) return false;

  if ( mImpl->fieldId() != FieldImpl::CustomField ) return true;

  return mImpl->key() == field->mImpl->key();
}

Field *Field::createCustomField( const QString &label, int category,
                                 const QString &key, const QString &app )
{
  Field *field = new Field( new FieldImpl( FieldImpl::CustomField,
                                           category | CustomCategory,
                                           label, key, app ) );
  mCustomFields.append( field );

  return field;
}
