/***************************************************************************
   Copyright (C) 2007
   by Marco Gulino <marco@kmobiletools.org>

   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.

   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 General Public License for more details.

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

#ifndef KMOBILETOOLSVOIDENGINE_H
#define KMOBILETOOLSVOIDENGINE_H

#include <qobject.h>
#include <qptrlist.h>
#include "contactptrlist.h"
#include <kabc/addressbook.h>
#include <klibloader.h>
#include <kabc/phonenumber.h>
#include <kdebug.h>
#include <klocale.h>

#include "weaver.h"
#include "smslist.h"
#include "sms.h"
#include "kmobiletools_devices.h"
#include "engineslist.h"
#include "engineloader.h"
#include "config.h"

#ifdef HAVE_KCAL
#include <libkcal/event.h>
#include "calendar.h"
#endif

#define PB_SIM_TEXT i18n("Sim PhoneBook")
#define PB_PHONE_TEXT i18n("Mobile PhoneBook")
#define PB_DATACARD_TEXT i18n("Datacard PhoneBook")

/**
@author Marco Gulino
*/

class KPluginInfo;

using namespace KMobileTools;

class kmobiletoolsJob : public ThreadWeaver::Job
{
    Q_OBJECT
    public:
        kmobiletoolsJob (const QString &owner, QObject* parent = 0 , const char* name = 0);
        kmobiletoolsJob (kmobiletoolsJob *pjob, QObject* parent = 0 , const char* name = 0);
      enum JobType
        { initPhone=0, pollStatus=-1, fetchSMS=-2, fetchAddressBook=-3, fetchPhoneInfos=-4, testPhoneFeatures=-5,
        syncDateTimeJob=-6, selectSMSSlot=-7, selectCharacterSet=-8, sendSMS=-9, storeSMS=-10, sendStoredSMS=-11, addAddressee=-12, delAddressee=-13, editAddressee=-14,
        smsFolders=-15, delSMS=-16, fetchKCal=-17 };

        virtual JobType type() = 0;
        const QString typeString();
    protected slots:
        void slotPercentDone();
        void slotPercentDone(int);
    protected:
        int ji_percent;
    signals:
        void percentDone(int);
};


// class KMTAddress : public

using namespace ThreadWeaver;

/**
 * @author Marco Gulino
 */
class kmobiletoolsEngine : public QObject
{
    Q_OBJECT

    public:
        /**
         * This enum type defines the type of phone book memory slot.
         *
         * - PB_SIM : Sim card
         * - PB_Phone : Phone
         * - PB_DataCard : Data card
         */
        enum PhoneBookMemorySlot { PB_SIM = 2, PB_Phone = 1, PB_DataCard = 4 };

//      enum SMSSlots { SMS_SIM = 0x1, SMS_PHONE = 0x2, SMS_DATACARD = 0x4 };

        enum ProbeType { PROBE_Manufacturer = 0x1, PROBE_Model = 0x2, PROBE_Revision = 0x4,
                         PROBE_IMEI = 0x8, PROBE_SMSSLOTS = 0x10, PROBE_PBSLOTS = 0x20,
                         PROBE_CHARSET = 0x40, PROBE_SMSCENTER=0x80 };
        enum DialActions { DIAL_DIAL = 0x1, DIAL_HANGUP = 0x2 };

        /**
         * This enum type defines the phone manufacturers.
         *
         * - Unknown : Unknown manufacturer
         * - Motorola : Motorola
         * - Siemens : Siemens
         * - SonyEricsson : Sony Ericcson
         * - Nokia : Nokia
         */
        enum ManufacturerEnum { Unknown = 0, Motorola = 1, Siemens = 2,
                                SonyEricsson = 3, Nokia = 4 };

        /**
         * Creates a new kmobiletoolsEngine object.
         * @param parent the parent QObject
         * @param name the object name
         */
        kmobiletoolsEngine(QObject *parent = 0, const char *name = 0);

        /**
         * Destroys a kmobiletoolsEngine object.
         */
        virtual ~kmobiletoolsEngine();
        ThreadWeaver::Weaver *ThreadWeaver() { return weaver; }
        /**
         * Retrieves the phone manufacturer.
         * @return the phone manufacturer
         */
        QString rawManufacturer() const { return s_manufacturer; }

        /**
         * Retrieves the phone model.
         * @return the phone model
         */
        QString model() const { return s_model; }

        /**
         * Retrieves the phone raw IMEI.
         * The IMEI is a number unique to every GSM and UMTS mobile phone.
         * @return the phone raw IMEI
         */
        QString imei() const { return s_imei; }

        /**
         * Retrieves the phone firmware revision.
         * @return the phone firmware revision
         */
        QString revision() const { return s_revision; }

        /**
         * Retrieves the SMS center number.
         * @return the SMS center number
         */
        QString smsCenter() const { return s_smscenter; }

        /**
         * Retrieves the new SMS number.
         * @return the new SMS number
         */
        int newSMSCount() { return s_newSMS; }

        /**
         * Retrieves the total SMS number.
         * @return the total SMS number
         */
        int totalSMSCount() { return s_totalSMS; }

        /**
         * Retrieves the manufacturer ID.
         * @return the manufacturer ID
         * @todo Change function name (manufacturerId)
         */
        int manufacturer() { return i_manufacturer; }

        /**
         * Retrieves the phone contact list.
         * @return phone contact list
         */
        ContactPtrList* addresseeList() { return p_addresseeList; }

        /**
         * Retrieves the phone SMS list.
         * @return the phone SMS list
         */
        SMSList* smsList() const { return p_smsList; };

        /**
         * Retrieves the phone SMS folders.
         * @return the phone SMS folders
         */
        QStringList smsFolders() { return s_folders; };

        /**
         * Retrieves the numbers of phonebook memory slots.
         * @return the numbers of phonebook memory slots
         */ 
        virtual int availPbSlots() = 0;

        /**
         * Set the SMS slot (sim, phone, datacard) to be used.
         * @param slot the slot that be used
         */
        void setSMSSlot(int slot){ sms_slot = slot; }

        /**
         * Retrieves the SMS slot used.
         * @return the sms slot used.
         */
        int smsSlot() { return sms_slot; }

        /**
         * Retrieves if phone is connected.
         * @return true if phone is connected.
         */
        bool isConnected() { return b_connected; }
        /**
         * Shows if mobile phone can encode text in PDU mode.
         * @return true if mobile phone is PDU able.
         */
        virtual bool pdu()=0; /// @TODO check removal

        /**
         * Ask engine to close before calling the destructor.
         */
        virtual void queryClose();
        virtual QString shortDesc();
        virtual QString longDesc();
        /**
         * The engine name provided in the .desktop file
         */

        #ifdef HAVE_KCAL

            /**
             * Retrieves the phone calendar.
             * @return the phone calendar
             */
            Calendar *calendar() { return p_calendar; }

        #endif
        virtual QString currentDeviceName() const { return QString::null; }
        virtual QString engineLibName() const=0;
        KPluginInfo *pluginInfo();


    protected:
        KPluginInfo *p_pluginInfo;
        /**
         * Phone SMS list.
         */
        SMSList *p_smsList;

        SMSList *p_diffSMSList;

//         KABC::AddressBook *p_addressbook;

        ThreadWeaver::Weaver *weaver;

        QPtrList <ThreadWeaver::Job> jobs;

        /**
         * Enqueue a job.
         */
        void enqueueJob(kmobiletoolsJob *job);

        /**
         * Phone raw manufacturer Id.
         */
        QString s_manufacturer;

        /**
         * Phone model.
         */
        QString s_model;

       /**
        * Phone raw imei.
        */
        QString s_imei;

        /**
         * Phone firmware revision.
         */
        QString s_revision;

        /**
         * SMS center number.
         */
        QString s_smscenter;

        /**
         * Phone manufacturer.
         */
        int i_manufacturer;

        int i_currentPBMemSlot;

        /**
         * New SMS number.
         */
        int s_newSMS;

        /**
         * Total SMS number.
         */
        int s_totalSMS;

        /**
         * Phone contact list.
         */
        ContactPtrList* p_addresseeList;

        /**
         * Phone SMS folders.
         */
        QStringList s_folders;

        /**
         * Phone SMS slot used.
         */
        int sms_slot;

        int i_suspendStatusJobs;

        DevicesInfoList devicesList;

        DeviceInfos *p_foundDevice;

        /**
         * True if phone is connected.
         */
        bool b_connected;
        bool b_ownweaver;

        #ifdef HAVE_KCAL

            /**
             * The phone calendar.
             */
            Calendar *p_calendar;

        #endif

    public slots:
        /** TODO implement this
            virtual bool changePhoneBookSlot (PhoneBookMemorySlot slot) = 0;
            virtual bool changeSMSMemSlot (SMS::MemorySlot slot ) = 0;
            virtual int parseSMSList() = 0;
            virtual int parseAddressBook() = 0;
        */

        virtual void retrieveSMSList() = 0;
        virtual void retrieveAddressBook() = 0;
        virtual void pollPhoneStatus() = 0;
        virtual void processSlot(Job* job);
        virtual void getPhoneInfos() = 0;
        virtual void dial(DialActions, const QString & =QString::null ) = 0;
        /**
         * This slot is when deviceList has finished probing devices.
         * Here we can start searching the list for our mobile, and start connecting to the device.
         * Reimplement to correctly initialize engines.
         */
        virtual void initPhone() = 0;
        /**
         * Start searching for our mobile phone.
         * This has to be reimplemented to start probing devices with correct initialization parameters.
         */
        virtual void probePhone() = 0;
        virtual void slotAddAddressee(QValueList<KABC::Addressee>*) = 0;
        virtual void slotDelAddressee(QValueList<KABC::Addressee>*) = 0;
        virtual void slotDelSMS(SMS*) = 0;
        virtual void slotStoreSMS(const QString &number, const QString &text) = 0;
        virtual void slotSendSMS(const QString &number, const QString &text) = 0;
        virtual void slotStoreSMS(SMS*) = 0;
        virtual void slotSendSMS(SMS*) = 0;
        virtual void slotSendStoredSMS(SMS*) = 0;
        virtual void slotEditAddressee(KABC::Addressee*, KABC::Addressee*) = 0;
        virtual QStringList encodings() = 0;
        int currentPBMemSlot() { return i_currentPBMemSlot; }
        void setCurrentPBMemSlot(int type) { i_currentPBMemSlot=type; }
        virtual void stopDevice() { weaver->suspend(true); }
        virtual void resumeDevice() { weaver->suspend(false); emit resumed(); }
        virtual void weaverSuspended() { emit suspended(); }
        virtual void setDevice ( const QString &deviceName) = 0; /// @TODO check removal
        virtual void closeDevice() = 0; /// @TODO check removal
        /**
         * Returns information for probing devices.
         * @param job the threaded job doing the probe.
         * @param fullprobe if retrieving every information avaliable, or IMEI only (fastest).
         * @param deviceName full path of device to be probed.
         * @param params List of parameter for initializing the device.
         * @return An object of type DeviceInfos containing all the informations for this device.
         */
        virtual DeviceInfos probeDevice(ThreadWeaver::Job *job, bool fullprobe, const QString &deviceName, const QStringList &params) const= 0; /// @TODO RENAME
        void suspendStatusJobs(bool suspend)  { if(suspend) i_suspendStatusJobs++; else i_suspendStatusJobs--; }
        int statusJobsSuspended() { return i_suspendStatusJobs; }
        virtual void fetchCalendar() = 0;
        virtual void switchToFSMode();

    protected slots:
        virtual void devConnected() { b_connected = true; }
        virtual void devDisconnected() { b_connected = false; }

    signals:
        /**
         * This signal is emitted when KMobileTools finish a task.
         */
        void jobFinished(kmobiletoolsJob::JobType job);
        /**
         * This signal is emitted when the phone is disconnected.
         */
        void disconnected();

        /**
         * This signal is emitted when the phone is connected.
         */
        void connected();

        /**
         * This signal is emitted when an error is occurred.
         */
        void error();

        /**
         * This signal is emitted when a new SMS is received.
         */
        void newSMS(SMS*);

        /**
         * This signal is emitted when something is changed in the engine and
         * ask gui to update the page.
         */
        void updateInfoPage(int);

        /**
         * This signal is emitted when a SMS folder is added
         */
        void addSMSFolders();

        /**
         * This signal is emitted every phone poll.
         * @param signal the signal level in percentual.
         */
        void signal(int);

        /**
         * This signal is emitted every phone poll.
         * @param charge the charge level in percentual.
         */
        void charge(int);

        /**
         * This signal is emitted every phone poll.
         * Charge type is 1 when phone is connected to the adapter.
         * @param chargetype the type of charge
         */
        void chargeType(int);

        /**
         * This signal is emitted every phone poll.
         * @param ringing true if phone is ringing
         * @todo emit only if phone is ringing
         */
        void isRinging(bool);

        /**
         * This signal is emitted when the phone book is updating.
         * @todo to be deleted
         */
        void phoneBookUpdated(int, const ContactPtrList&);

        /**
         * This signal is emitted when the phone book is updated.
         */
        void phoneBookUpdated();

        /**
         * This signal is emitted when SMS list is updated.
         */
        void smsListUpdated();

        /**
         * This signal is emitted every phone infos fetch.
         * @param name the name of the network.
         */
        void networkName( const QString &);

        /**
         * This signal is emitted when is needed a new fetch.
         */
        void addressBookToUpdate();

        /**
         * This signal is emitted when the engine is suspended.
         */
        void suspended();

        /**
         * This signal is emitted when the engine is resumed.
         */
        void resumed();

        /**
         * This signal is emitted when a job is enqueued.
         */
        void jobEnqueued(kmobiletoolsJob *);

        /**
         * This signal is emitted when a SMS is added.
         */
        void smsAdded(const QCString&);

        /**
         * This signal is emitted when a SMS is deleted.
         */
        void smsDeleted(const QCString&);

        /**
         * This signal is emitted when a SMS is modified.
         */
        void smsModified(const QCString&);

        /**
         * This signal is emitted when lock file is invalid.
         */
        void invalidLockFile(const QString &);

        /**
         * This signal is emitted when phonebook is full.
         */
        void fullPhonebook();

        /**
         * This signal is emitted when calendar is parsed.
         */
        void calendarParsed();
};

#endif

