#ifndef _KPILOT_PILOTADDRESS_H
#define _KPILOT_PILOTADDRESS_H
/* pilotAddress.h			KPilot
**
** Copyright (C) 1998-2001 by Dan Pilone
** Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
**
** This is a wrapper for pilot-link's address structures.
*/

/*
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 of the License, or
** (at your option) any later version.
**
** This program 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 Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program in a file called COPYING; if not, write to
** the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
** MA 02111-1307, USA.
*/

/*
** Bug reports and questions can be sent to kde-pim@kde.org
*/

#include <pi-macros.h>
#include <pi-address.h>

#include <kabc/addressbook.h>

#include "pilotAppCategory.h"
#include "pilotDatabase.h"

/** @brief A wrapper class around the Address struct provided by pi-address.h
 *
 * This class allows the user to set and get address field values.
 * For everything but phone fields, the user can simply pass the
 * the pi-address enum for the index for setField() and getField() such
 * as entryLastname.
 *
 * Phone fields are a bit trickier.  The structure allows for 8 possible
 * phone fields with 5 possible slots.  That means there could be three
 * fields that don't have available storage. The setPhoneField() method
 * will attempt to store the extra fields in a custom field if there
 * is an overflow.
 *
 * There are eight possible fields for 5 view slots:
 * - fields: Work, Home, Fax, Other, Pager, Mobile, E-mail, Main
 * - slots: entryPhone1, entryPhone2, entryPhone3, entryPhone4, entryPhone5
 *
 * Internally in the pilot-link library, the AddressAppInfo phone
 * array stores the strings for the eight possible phone values.
 * Their English string values are :
 * - phone[0] = Work
 * - phone[1] = Home
 * - phone[2] = Fax
 * - phone[3] = Other
 * - phone[4] = E-mail
 * - phone[5] = Main
 * - phone[6] = Pager
 * - phone[7] = Mobile
 *
 * Apparently, this order is kept for all languages, just with localized
 * strings.  The implementation of the internal methods will assume
 * this order is kept. In other languages, main can replaced with
 * Corporation.
 */
namespace KABC
{
	class PhoneNumber;
}

class KDE_EXPORT PilotAddress : public PilotAppCategory
{
public:
	enum EPhoneType {
		eWork=0, eHome, eFax, eOther, eEmail, eMain,
		ePager, eMobile
		};

	PilotAddress(struct AddressAppInfo &appInfo);
	PilotAddress(struct AddressAppInfo &appInfo, PilotRecord* rec);
	PilotAddress(const PilotAddress &copyFrom);
	PilotAddress& operator=( const PilotAddress &r );
	bool operator==(const PilotAddress &r);

	~PilotAddress();

	/** Returns a text representation of the address. If richText is true, the
	 *  text is allowed to contain Qt-HTML tags.
	 */
	virtual QString getTextRepresentation(bool richText=false);

	/** Zeros the internal address info structure, in effect clearing
	*  out all prior set values
	*/
	void reset() { memset(&fAddressInfo, 0, sizeof(struct Address)); }

	/**
	*   @param text set the field value
	*   @param field int values associated with the enum defined in
	*  pi-address.h.
	*  The copied possible enum's are: (copied from pi-address.h on 1/12/01)
	*  enum { entryLastname, entryFirstname, entryCompany,
	*  entryPhone1, entryPhone2, entryPhone3, entryPhone4, entryPhone5,
	*  entryAddress, entryCity, entryState, entryZip, entryCountry,
	*  entryTitle, entryCustom1, entryCustom2, entryCustom3, entryCustom4,
	*  entryNote };
	*/
	void setField(int field, const QString &text);
	QString getField(int field) const;

    /**
      Return list of all email addresses.  This will search through our "phone"
	  fields and will return only those which are e-mail addresses.
     */
    QStringList getEmails() const;
	void setEmails(QStringList emails);

    /**
	Return list of all phone numbers.  This will search through our "phone"
	fields and will return only those which are not e-mail addresses.
	 */
	KABC::PhoneNumber::List getPhoneNumbers() const;
	void setPhoneNumbers(KABC::PhoneNumber::List list);

	QString getCategoryLabel() const;

	/** If the label already exists, uses the id; if not, adds the label
	*  to the category list
	*  @return false if category labels are full
	*/
	inline bool setCategory(const QString &label) { return setCat(fAppInfo.category,label); } ;


	/**
	*  @param type is the type of phone
	*  @param checkCustom4 flag if true, checks the entryCustom4 field
	*  for extra phone fields
	*  @return the field associated with the type
	*/
	QString getPhoneField(EPhoneType type, bool checkCustom4=true) const;

	/**
	*  @param type is the type of phone
	*  @param field is value to store
	*  @param overflowCustom is true, and entryPhone1 to entryPhone5 is full
	*  it will use entryCustom4 field to store the field
	*  @param overwriteExisting is true, it will overwrite an existing record-type
	*  with the field, else it will always search for the first available slot
	 * @return index of the field that this information was set to
	*/
	int setPhoneField(EPhoneType type, const QString &field,
		bool overflowCustom=true, bool overwriteExisting=true);

	/**
	* Returns the (adjusted) index of the phone number
	* selected by the user to be shown in the
	* overview of addresses. Adjusted here means
	* that it's actually an index into 3..8, the fields
	* that store phone numbers, so 0 means field 3 is selected.
	* @return # between 0 and 3, where 0 is entryPhone1 and 3 is entryPhone4
	*/
	int getShownPhone() const { return fAddressInfo.showPhone; }
	void setShownPhone(EPhoneType phoneType);
	int  getPhoneLabelIndex(int index) const { return fAddressInfo.phoneLabel[index]; }


	virtual void *pack_(void *, int *);
	void unpack(const void *, int = 0) { }

	static const int APP_BUFFER_SIZE;

	const struct Address *address() const { return &fAddressInfo; } ;

protected:
	// Get the pointers in cases where no conversion to
	// unicode is desired.
	//
	const char *getFieldP(int field) const
		{ return fAddressInfo.entry[field]; }

private:
	void _copyAddressInfo(const struct Address &copyFrom);
	int _getNextEmptyPhoneSlot() const;

	/** @return the phone label number (0 through 8) that corresponds
	*  to the phoneType; do O(n) search though the phoneLabels array
	*/
	int _getAppPhoneLabelNum(const QString &phoneType) const;

	/** @return entryPhone1 to entryPhone5 if the appTypeNum number is
	*  found in the phoneLabel array; return -1 if not found
	*/
	int _findPhoneFieldSlot(int appTypeNum) const;

	void _loadMaps();

	/** pilotToPhone map tracks from PilotAddress types to PhoneNumber types */
	QMap < int, int> pilotToPhoneMap;

	struct AddressAppInfo &fAppInfo;
	struct Address fAddressInfo;
};


typedef PilotAppInfo<AddressAppInfo,unpack_AddressAppInfo, pack_AddressAppInfo> PilotAddressInfo;


#endif
