#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <sys/file.h>
#include <unistd.h>
#include <errno.h>
#include <ctype.h>
#include <libconfig.h>

#include "log.h"
#include "libuv_dbus.h"
#include "server_addr.h"

#ifdef PLATFORM_R16
#define DEVICE_CFG_FILE         ("/mnt/UDISK/dev.conf")
#else
#define DEVICE_CFG_FILE         ("./dev.conf")
#endif

static config_t g_cfgInfo;

void InitCfgToCfgFile(config_t* pCfg)
{
    config_setting_t *pRoot, *pSetting, *pGlobalgrp, *pLogGrp, *pSubGrp;

    if(pCfg == NULL)
    {
        return;
    }

    pRoot = config_root_setting(pCfg);

    pGlobalgrp = config_setting_add(pRoot, "Global", CONFIG_TYPE_GROUP);

    pSetting = config_setting_add(pGlobalgrp, "ServerMode", CONFIG_TYPE_INT);
    config_setting_set_int(pSetting, PUBLISH_MODE);

    pLogGrp = config_setting_add(pGlobalgrp, "Log", CONFIG_TYPE_GROUP);

    pSetting = config_setting_add(pLogGrp, "Enable", CONFIG_TYPE_BOOL);
    config_setting_set_bool(pSetting, TRUE);

    pSetting = config_setting_add(pLogGrp, "Level", CONFIG_TYPE_INT);
    config_setting_set_format(pSetting, CONFIG_FORMAT_HEX);
    config_setting_set_int(pSetting, 0x000003FF);
    
    pSubGrp = config_setting_add(pLogGrp, "LogToEMail", CONFIG_TYPE_GROUP);
    pSetting = config_setting_add(pSubGrp, "Enable", CONFIG_TYPE_BOOL);
    config_setting_set_bool(pSetting, FALSE);
    pSetting = config_setting_add(pSubGrp, "EMail", CONFIG_TYPE_STRING);
    config_setting_set_string(pSetting, "pv1_es2@163.com");

    pSetting = config_setting_add(pLogGrp, "LogToFile", CONFIG_TYPE_BOOL);
    config_setting_set_bool(pSetting, TRUE);

    pSetting = config_setting_add(pLogGrp, "LogToServer", CONFIG_TYPE_BOOL);
    config_setting_set_bool(pSetting, TRUE);

    pSubGrp = config_setting_add(pLogGrp, "LogToUDPServer", CONFIG_TYPE_GROUP);
    pSetting = config_setting_add(pSubGrp, "Enable", CONFIG_TYPE_BOOL);
    config_setting_set_bool(pSetting, FALSE);
    pSetting = config_setting_add(pSubGrp, "UdpServerIp", CONFIG_TYPE_STRING);
    config_setting_set_string(pSetting, "10.240.84.163");
    pSetting = config_setting_add(pSubGrp, "UdpBasePort", CONFIG_TYPE_INT);
    config_setting_set_int(pSetting, 10000);


    if(!config_write_file(pCfg, DEVICE_CFG_FILE))
    {
        LOG_EX(LOG_Error, "Create Configure File %s Error\n", DEVICE_CFG_FILE);
    }
}

int CfgGetIntValueV2(const char* pTags, int defValue, int* pErr)
{
    char* pSvrMode = NULL;
    char cmdBuf[MAX_PATH];
    int iValue = defValue;

    memset(cmdBuf, 0, MAX_PATH);

    sprintf(cmdBuf, "cat %s | grep %s | awk '{print $3}' | cut -d \";\" -f 1",
        DEVICE_CFG_FILE,
        pTags);

    GetShellExecResult(cmdBuf, &pSvrMode);

    if(pSvrMode == NULL)
    {
        if(pErr)
        {
            *pErr = -ERR_NO_ITEMS;
        }
        return defValue;
    }

    iValue = strtol(pSvrMode, NULL, 10);
    free(pSvrMode);

    if(errno == EINVAL || errno == ERANGE)
    {
        if(pErr)
        {
            *pErr = -ERR_STR_CONVERT;
        }

        return defValue;
    }

    if(pErr)
    {
        *pErr = 0;
    }
    return iValue;
}

int CfgGetIntValueV1(const char* pTags, int defValue, int* pErr)
{
    int iValue = defValue;

    if(pTags == NULL || strlen(pTags) == 0)
    {
        if(pErr)
        {
            *pErr = -ERR_INPUT_PARAMS;
        }

        return defValue;
    }

    if(!config_lookup_int(&g_cfgInfo, pTags, &iValue))
    {
        if(pErr)
        {
            *pErr = -ERR_READ_FILE;
        }

        return defValue;
    }

    *pErr = 0;

    return iValue;
}

int CfgGetIntValue(const char* pTags, int defValue)
{
    int iValue = defValue;

    if(pTags == NULL || strlen(pTags) == 0)
    {
        return defValue;
    }

    if(!config_lookup_int(&g_cfgInfo, pTags, &iValue))
    {
        return defValue;
    }

    return iValue;
}

void CfgSetIntValue(const char* pTags, int iValue)
{
    config_setting_t *pRoot, *pGlobalgrp, *pSet;

    LOG_EX(LOG_Debug, "Set: %s --> %d\n", pTags, iValue);

    if(pTags == NULL || strlen(pTags) == 0)
    {
        LOG_EX(LOG_Error, "Input Params error: pTags = [%s]\n", pTags ? pTags : "NULL");
        return;
    }

    pRoot = config_root_setting(&g_cfgInfo);

    if(pRoot == NULL)
    {
        LOG_EX(LOG_Error, "pRoot = NULL\n");
        return;
    }

    pGlobalgrp = config_setting_get_member(pRoot, "Global");

    if(pGlobalgrp == NULL)
    {
        LOG_EX(LOG_Error, "pGlobalgrp = NULL\n");
        return;
    }
    
    pSet = config_setting_get_member(pGlobalgrp, pTags);

    if(!pSet)
    {
        pSet = config_setting_add(pGlobalgrp, pTags, CONFIG_TYPE_INT);
    }

    if(pSet == NULL)
    {
        LOG_EX(LOG_Error, "pSet = NULL\n");
        return;
    }

    config_setting_set_int(pSet, iValue);
   

    if(!config_write_file(&g_cfgInfo, DEVICE_CFG_FILE))
    {
        LOG_EX(LOG_Error, "Set %s Value Error\n", pTags);
    }
}

char* CfgGetStringValue(const char* pTags, char* pDefValue)
{
    char* pValue = pDefValue;
    
    if(pTags == NULL || strlen(pTags) == 0)
    {
        return pDefValue;
    }

    if(!config_lookup_string(&g_cfgInfo, pTags, (const char**)&pValue))
    {
        return pDefValue;
    }

    return pValue;
}

double CfgGetFloatValue(const char* pTags, double defValue)
{
    double dValue = defValue;

    if(pTags == NULL || strlen(pTags) == 0)
    {
        return defValue;
    }

    if(!config_lookup_float(&g_cfgInfo, pTags, &dValue))
    {
        return defValue;
    }

    return dValue;
}

int CfgGetBoolValue(const char* pTags, int defValue)
{
    int iValue = defValue;

    if(pTags == NULL || strlen(pTags) == 0)
    {
        return defValue;
    }

    if(!config_lookup_bool(&g_cfgInfo, pTags, &iValue))
    {
        return defValue;
    }

    return iValue;
}

void CfgFileInit(void)
{
    //config_setting_t *pRoot, *pSetting;
    
    config_init(&g_cfgInfo);

#if 0
    config_set_options(&g_cfgInfo,
                     (CONFIG_OPTION_SEMICOLON_SEPARATORS
                      | CONFIG_OPTION_COLON_ASSIGNMENT_FOR_GROUPS
                      | CONFIG_OPTION_OPEN_BRACE_ON_SEPARATE_LINE));
#endif

    config_set_tab_width(&g_cfgInfo, 4);

    if(access(DEVICE_CFG_FILE, F_OK) != 0)
    {
        InitCfgToCfgFile(&g_cfgInfo);
    }
    else if(!config_read_file(&g_cfgInfo, DEVICE_CFG_FILE))
    {
        LOG_EX(LOG_Error, "Read Configure File %s Error\n", DEVICE_CFG_FILE);
        return;
    }
}
