#ifndef LIBUV_DEBUS_H
#define LIBUV_DEBUS_H
#include "smart_sound.h"

#include <uv.h>
#include <dbus/dbus.h>
#include "json_struct.h"
#include "config_engine.h"

#ifdef __cplusplus
extern "C" {
#endif
#define 	SAFE_STRING_VALUE(s)					(s ? s : "")
#define     R16_TINA_KEY_EVENT_PATH                 ("/dev/input/event2")
#define     DBUS_MESSAGE_INTERFACE_NAME             "netease.ihw.SmartAudio"

#define     DBUS_PATH_HEAD                          "/netease/ihw/"
#define     DBUS_INTERFACE_HEAD                     "netease.ihw."

#define     DBUS_MSG_MAX_PAD_SIZE                   (1024 * 1024 * 2)
#define     LIBUV_CURRENT_TIME_S()                  (uv_hrtime() / 1000000000)
#define     LIBUV_CURRENT_TIME_MS()                 (uv_hrtime() / 1000000)
#define     LIBUV_CURRENT_TIME_US()                 (uv_hrtime() / 1000)
#define     MODULE_ALIAS_NAME(i)                    (strrchr(g_pModInfoTable[i].modAliase, '.') + 1)

#define     HEART_SEND_DELAY                (5000)
#define     HEART_LOST_DELAY                (20000)

typedef enum
{
    WIFI_CONNECTED      = 0,
    WIFI_DISCONNECTED   = 1,
} WIFI_STATUS;

typedef struct
{
    int wifi_evt;
} WIFI_STATUS_PRO, *PWIFI_STATUS_PRO;

typedef struct
{
    int             isReady;
    int             year;
    unsigned char   days[366];
} WORKDAY_INFO, *PWORKDAY_INFO;

typedef struct
{
    int32_t         msgSrc;                     ///< message who send
    uint32_t        msgDests;                   ///< who need receive message(not only one)    
#if USED_SHM_TO_DBUS                            
    uint32_t        tmTickMSec;                 ///< timestamp of second
#endif                                          
    uint32_t        busCmd;                     ///< command of message
    uint32_t        msgSize;                    ///< how many bytes of this message
    uint32_t        msgKey;                     ///< share key for copy large message
    char*           pMsg;                       ///< message context if has
    int             isBstMsg;
} DBUS_MSG_PACK, *PDBUS_MSG_PACK;

typedef struct DBUS_MSG_PROC
{
    int             msgFrom;    ///< 0: Boardcast Msg, 1: P2P Message
    DBUS_MSG_PACK   msgContent;

    struct DBUS_MSG_PROC     *next, *prev;
} *PDBUS_MSG_PROC;

typedef void (*OnDBusAsyncSendTo)(int err);
typedef PDBUS_MSG_PACK (*OnDBusMessage)(uv_loop_t* pLoop, DBusConnection* pConn, PDBUS_MSG_PACK pMsg);
typedef void (*OnDaemonMsg)(MODULE_NAME modName, int status);
typedef void (*OnKeyEvent)(uint16_t uType, uint16_t uKey, int32_t iValue);

typedef struct 
{
    MODULE_NAME     modName;                    ///< Module Name 
    const char*     modPath;                    ///< Attach to dbus path
    const char*     modAliase;                  ///< Attach to dbus bus name
} MOD_INFO_TABLE, *PMOD_INFO_TABLE;             


typedef struct                                  
{                                               
    uv_loop_t*          pLoop;				    ///< libuv default main loop 
    uv_loop_t*          pUserLoop;			    ///< libuv user main loop 
    DBusConnection*     pBus;				    ///< D-Bus object
    MODULE_NAME         modName;			    ///< Process name
    const char*         pBusName;			    ///< D-Bus object's interface name
    const char*         pBusPath;			    ///< D-Bus object's path name
    OnDBusMessage       onMsgCb;			    ///< D-Bus receive message callback
    OnKeyEvent          onKeyCb;			    ///< Keyboard event callback
    OnDaemonMsg         onHblCb;			    ///< Process HBL event callback
    OnCfgMsg            onCfgCb;			    ///< Configure message callback
//    unsigned int        uDaemon[MODULE_MAX];    ///< Daemon Service
} LIBUV_DBUS_PARAMS, *PLIBUV_DBUS_PARAMS;

static MOD_INFO_TABLE g_pModInfoTable[] = 
{    
    {MODULE_CONTROLLER,        DBUS_PATH_HEAD"controller",     DBUS_INTERFACE_HEAD"controller"},
    {MODULE_ALARM,             DBUS_PATH_HEAD"alarm",          DBUS_INTERFACE_HEAD"alarm"},
    {MODULE_CALL,              DBUS_PATH_HEAD"call",           DBUS_INTERFACE_HEAD"call"},
    {MODULE_VOICEENGINE,       DBUS_PATH_HEAD"voice_engine",   DBUS_INTERFACE_HEAD"voice_engine"},
    {MODULE_PLAYER,            DBUS_PATH_HEAD"player",         DBUS_INTERFACE_HEAD"player"},
    {MODULE_CONFIGURE,         DBUS_PATH_HEAD"config",         DBUS_INTERFACE_HEAD"config"},
    {MODULE_OTA,               DBUS_PATH_HEAD"ota",            DBUS_INTERFACE_HEAD"ota"},
    {MODULE_WIFI,              DBUS_PATH_HEAD"wifi",           DBUS_INTERFACE_HEAD"wifi"},
    {MODULE_BT,                DBUS_PATH_HEAD"bt",             DBUS_INTERFACE_HEAD"bt"},
    {MODULE_KPLAYER,           DBUS_PATH_HEAD"kplayer",        DBUS_INTERFACE_HEAD"kplayer"},
    {MODULE_KPLAYER_TEST,      DBUS_PATH_HEAD"kplayerTest",    DBUS_INTERFACE_HEAD"kplayerTest"},
    {MODULE_SPLAYER,           DBUS_PATH_HEAD"splayer",        DBUS_INTERFACE_HEAD"splayer"},
    {MODULE_SPLAYER_TEST,      DBUS_PATH_HEAD"splayerTest",    DBUS_INTERFACE_HEAD"splayerTest"},
    {MODULE_LIGHT_MCU,         DBUS_PATH_HEAD"light_mcu",      DBUS_INTERFACE_HEAD"light_mcu"},
    {MODULE_BLUEKC,            DBUS_PATH_HEAD"blukc",          DBUS_INTERFACE_HEAD"blukc"},
    {MODULE_BLUEKC_TEST,       DBUS_PATH_HEAD"bluekcTest",     DBUS_INTERFACE_HEAD"bluekcTest"},
    {MODULE_MANUFACTURE,       DBUS_PATH_HEAD"manufacture",    DBUS_INTERFACE_HEAD"manufacture"},
    {MODULE_BT_DEMO,           DBUS_PATH_HEAD"btdemo",         DBUS_INTERFACE_HEAD"btdemo"},
    {MODULE_SKINS,             DBUS_PATH_HEAD"skins",          DBUS_INTERFACE_HEAD"skins"},
    {MODULE_LOG_CTRL,          DBUS_PATH_HEAD"logCtrl",        DBUS_INTERFACE_HEAD"logCtrl"},
    {MODULE_WIRELESSTEST,      DBUS_PATH_HEAD"wirelessTest",      DBUS_INTERFACE_HEAD"wirelessTest"},
    {MODULE_WIRELESSTEST_DEMO, DBUS_PATH_HEAD"wirelessTestDemo",  DBUS_INTERFACE_HEAD"wirelessTestDemo"},
    {MODULE_MANUFACTURE_CONTROLLER, DBUS_PATH_HEAD"manufacture_controller",  DBUS_INTERFACE_HEAD"manufacture_controller"},
    {MODULE_WIFI_DEMO, DBUS_PATH_HEAD"wifiDemo",  DBUS_INTERFACE_HEAD"wifiDemo"},
};

PLIBUV_DBUS_PARAMS DBusLibuvGetRuntime(void);
MODULE_NAME DBusLibGetModName(void);
uv_loop_t* GetDBusDefaultLoop(void);

void RunUVLoop(uv_loop_t *pLoop);

PDBUS_MSG_PACK DBusGetMessage(void);
void DBusMsgCleanup(PDBUS_MSG_PACK pMsg);

DBusConnection* DBusWithLibuvInit(uv_loop_t*            pUserLoop, 
                                const char*             pBusName, 
                                OnDBusMessage           cbOnMsg,
                                OnDaemonMsg             cbOnHbl,
                                OnKeyEvent              cbOnKey,
                                int*                    pErrno);

int DBusJsonSendToCommandAsync(DBusConnection*          pBus, 
                                const char*             pBusName,
                                uint32_t                busCmd,
                                JSON_ENGINE_TYPE        type,
                                void*                   pStruct,
                                int                     iSize,
                                OnDBusAsyncSendTo       cbSendTo,
                                int                     enBase64);

int DBusJsonSendToCommand(DBusConnection*               pBus, 
                                const char*             pBusName,
                                uint32_t                busCmd,
                                JSON_ENGINE_TYPE        type,
                                void*                   pStruct,
                                int                     enBase64);
                                
int DBusJsonBoardcastCommand(DBusConnection*            pBus, 
                                uint32_t                msgToMask, 
                                uint32_t                busCmd, 
                                JSON_ENGINE_TYPE        type,
                                void*                   pStruct,
                                int                     enBase64);

int DBusBoardcastCommand(DBusConnection *pBus,
                                  uint32_t        msgToMask,
                                  uint32_t        busCmd,
                                  const char *pContext);

int DBusSendToCommand(DBusConnection *pBus,
                               const char   *pBusName,
                               uint32_t     busCmd,
                               const char   *pContext);

void HeartDaemonUpgrade(int iWatcher);
void HeartDaemonInit(MODULE_NAME mod, int msHblTout, OnDaemonMsg cb);
void HeartDaemonHblCheck(void);

int DBusWithLibuvCfgInit(OnCfgMsg cbOnCfgMsg);
int GetShellExecResult(const char *pCmd, char **pResult);
int CopyFile(const char *pSrc, const char *pDest);
int CopyFileWithSize(const char *pSrc, const char *pDest, int iSize);
int ReadFileToBuf(const char *pSrc, unsigned char *pBuf, int iSize);
void SystemSafeReboot(void);

typedef void (*OnAlarmTimer)(unsigned int tmId, unsigned int status, void* pUserData);
int AlarmTimerInit(uv_loop_t *pLoop);
int AlarmTimerCleanup(void);
int AlarmTimerRemove(unsigned int tmId);
#if 0
unsigned int AlarmTimerAdd(struct tm *pOnTime, unsigned int repMode, OnAlarmTimer pOnTimerCb, void *pUserData, int *pError);
#endif
unsigned int AlarmTimerAdd(int      year,
                            int     month,
                            int     day,
                            int     hour,
                            int     minute,
                            int     second,
                            int     weekDay,
                            int     repMode,
                            OnAlarmTimer    pOnTimerCb,
                            int     priority,
                            void    *pUserData,
                            int     *pError);

int CurrentIsWorkDay(int year, int day);
int IsHolidayDBSynced(void);
const char* DumpTimerRepeatModeString(int mode);
unsigned long long GetPartitionFreeSize(const char *pPartPath);
WIFI_STATUS GetCurrWIFIConnStatus(void);
const char* ErrcodeToString(int errCode);
const char* DBusCmdToString(DBUS_CMD cmd);
const char* ModuleNameToString(MODULE_NAME modName);

char* GetCpuSerial(void);
char* GetCpuChipId(void);
char* GetCurrentVersion(void);

void CfgFileInit(void);
int CfgGetIntValue(const char* pTags, int defValue);
int CfgGetIntValueV1(const char* pTags, int defValue, int* pErr);
int CfgGetIntValueV2(const char* pTags, int defValue, int* pErr);
int GetServerModeFromCC(int defValue, int* pErr);
char* CfgGetStringValue(const char* pTags, char* pDefValue);
double CfgGetFloatValue(const char* pTags, double defValue);
int CfgGetBoolValue(const char* pTags, int defValue);
void SetHBLAutoExit(int flag);

extern char *strptime(const char *s, const char *format, struct tm *tm);
#ifdef __cplusplus
}
#endif 
#endif
