/*
 *
 *  Object Manager implementation of bluez5
 *
 *  Copyright (C) 2018  Emanoil Kotsev <deloptes@gmail.com>
 *
 *
 *  This file is part of libtdebluez.
 *
 *  libtdebluez 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.
 *
 *  libtdebluez 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 kbluetooth; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#ifndef OBJECTMANAGERIMPL_H_INCLUDED
#define OBJECTMANAGERIMPL_H_INCLUDED

#include <tqdbusconnection.h>
#include <tdelocale.h>

#include "interfaces/objectmanagerProxy.h"
#include "interfaces/agentmanager1Proxy.h"
#include "interfaces/profilemanager1Proxy.h"
#include "interfaces/healthmanager1Proxy.h"
#include "interfaces/propertiesProxy.h"

#include "adapterImpl.h"
#include "deviceImpl.h"

//using namespace org::bluez;

#define DBUS_CONN_NAME "TDEBluez"

#define DBUS_AUTH_SERVICE_PATH  "/org/trinitydesktop/tdebluez"
#define DEVICE_PIN_CAPABILITY "KeyboardDisplay"

namespace TDEBluetooth
{

class TDE_EXPORT ObjectManagerImpl : public org::freedesktop::DBus::ObjectManagerProxy
{
    TQ_OBJECT

public:
    ObjectManagerImpl(const TQString& service, const TQString& path, TQObject* parent = 0, const char* name = 0);

    virtual	~ObjectManagerImpl();
    typedef TQMap<TQString,org::freedesktop::DBus::PropertiesProxy*> PropertiesMap;
    typedef TQValueList<TQString> AdapterList;
    typedef TQValueList<TQString> DeviceList;
    typedef TQValueList<TQString> ConnectionList;
    //    typedef TQValueList<TQString> ServiceList;

    // --- helper to get private members of the class --- //
    //! to get information if TDEBluez is connected to D-Bus
    bool isConnectedToDBUS();
    //! pointer to the D-Bus connection
    TQT_DBusConnection* getConnection();
    //! to close the connection to D-Bus
    bool close();

    //
    AgentManager1Proxy* 	getAgentManager();
    ProfileManager1Proxy* getProfileManager();
    HealthManager1Proxy* getHealthManager();
    AdapterList 	getAdapters();
    DeviceList   	getDevices();
    //	ServiceList 	getServices();
    ConnectionList listConnections(const TQString&);


    //! to register the agent to D-Bus
    bool registerAgent(); //TQT_DBusError&
    //! to unregister the agent to D-Bus
    bool unregisterAgent(); //TQT_DBusError&
    //! to register the agent to D-Bus
    bool requestDefaultAgent(); //TQT_DBusError&

    bool isAgentRegistered();

    bool isAgentDefaultAgent();

private:
    bool initDBUS();
    void adapterPropertiesChanged(TQString path, const TQMap<TQString, TQT_DBusVariant>& changed_properties);
    void devicePropertiesChanged(TQString path, const TQMap<TQString, TQT_DBusVariant>& changed_properties);
    void mediaControlPropertiesChanged(TQString path, const TQMap<TQString, TQT_DBusVariant>& changed_properties);

private:
    //! TQt connection to D-Bus
    TQT_DBusConnection	dBusConn;
    AgentManager1Proxy*		agentManager;
    ProfileManager1Proxy*	profileManager;
    HealthManager1Proxy*		healthManager;
    PropertiesMap		adapters;
    PropertiesMap		devices;
    bool agentRegisteredStatus;
    bool agentIsDefaultAgent;

signals:
    // from ObjectManager
    void adapterAdded(const TQString&);
    void adapterRemoved(const TQString&);

    void deviceAdded(const TQString&);
    void deviceRemoved(const TQString&);

    void mediaControlAdded(const TQString&);
    void mediaControlRemoved(const TQString&);

    // from Adapter1
    void adapterNameChanged(const TQString&, const TQString&);
    //	void adapterModeChanged(const TQString&, const TQString&);
    void adapterAliasChanged(const TQString&, const TQString&);
    void adapterPowerOnChanged(const TQString&, bool state);
    void adapterClassChanged(const TQString&, TQ_UINT32 classvalue);
    void adapterDiscoverableTimeoutChanged(const TQString&, TQ_UINT32 timeout);
    // TODO: this should be same as modeChanged
    void adapterDiscoverableChanged(const TQString&, bool state);
    void adapterDiscoveringChanged(const TQString&, bool state);

    // from Device1
    void deviceAddressChanged(const TQString&, const TQString&);
    void deviceClassChanged(const TQString&, TQ_UINT32);
    void deviceNameChanged(const TQString&, const TQString&);
    void deviceAliasChanged(const TQString&, const TQString&);
    //		https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.gap.appearance.xml
    void deviceAppearanceChanged(const TQString&, TQ_UINT32);
    void deviceIconChanged(const TQString&, const TQString&);
    void devicePairedChanged(const TQString&, bool);
    void deviceTrustedChanged(const TQString&, bool);
    void deviceBlockedChanged(const TQString&, bool);
    void deviceLegacyPairingChanged(const TQString&, bool);
    void deviceRSSIChanged(const TQString&, TQ_INT16);
    void deviceConnectedChanged(const TQString&, bool);
    void deviceUUIDsChanged(const TQString&, TQStringList);
    void deviceAdapterChanged(const TQString&, const TQT_DBusObjectPath&);
    void deviceManufacturerDataChanged(const TQString&, TQT_DBusDataMap<TQ_UINT16>);
    void deviceServiceDataChanged(const TQString&, TQT_DBusDataMap<TQString>);
    void deviceTxPowerChanged(const TQString&, TQ_INT16);
    void deviceServicesResolvedChanged(const TQString&, bool);

    // from MediaControl1
    void mediaControlConnectedChanged(const TQString&, bool state);
    void mediaControlPlayerChanged(const TQString&, const TQT_DBusObjectPath&);

private slots:
    bool reconnect();

    // inherited from ObjectManager
    void slotInterfacesAdded(const TQT_DBusObjectPath& object, const TQT_DBusDataMap< TQString >& interfaces);
    void slotInterfacesRemoved(const TQT_DBusObjectPath& object, const TQStringList& interfaces);

    /**
     * parse properties changed on any interface
     * emit signal for the interface and property
     */
    void slotPropertiesChanged(const TQString& interface, const TQMap< TQString, TQT_DBusVariant >& changed_properties, const TQStringList& invalidated_properties);

}; // class ObjectManagerImpl

}; // namespace TDEBluetooth

#endif //OBJECTMANAGERIMPL_H_INCLUDED

// End of File
