#include "common.h"
#include "dy_utils/dy_common.h"
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>

bool ble_load_cfg(ble_var_t *var, struct adapter *adapter, GDBusProxy *proxy)
{
    int i = 0;
    GList *list;
    ble_scanner_cfg_t *scan_cfg = NULL;
    ble_advertising_cfg_t *adv_cfg = NULL;
    ble_slave_cfg_t *slave_cfg = NULL;
    ble_gatt_server_cfg_t *server_cfg = NULL;
    const char *interface;
    int dev_id;

    if (adapter == NULL)
    {
        dy_syslog(LOG_DEBUG, "no adapter found\n");
        return false;
    }
    adapter->enable = true;
    scan_cfg = &adapter->scan_cfg;
    scan_cfg->adapter = adapter;
    adv_cfg = &adapter->adv_cfg;
    adv_cfg->adapter = adapter;
    slave_cfg = &adapter->slave_cfg;
    slave_cfg->adapter = adapter;
    server_cfg = &adapter->server_cfg;
    server_cfg->adapter = adapter;

    interface = g_dbus_proxy_get_path(proxy);
    sscanf(interface, "/org/bluez/hci%d", &dev_id);
    adapter->dev_id = dev_id;

#if 1
    scan_cfg->enable = true;
    scan_cfg->scan_type = 0x00; // passive
    scan_cfg->filter_policy = 0x00;
    scan_cfg->interval = 0x0100;
    scan_cfg->window = 0x0010;
    scan_cfg->filter_dup = 0x00; // do not filter duplicates
    scan_cfg->own_type = LE_PUBLIC_ADDRESS;
#endif

    get_board_sn(var->sn_str);
    if (load_nodes_cfg(&var->nodes_cfg_table, NODES_CFG_PATH) == -1)
    {
        dy_syslog(LOG_ERR, "load nodes cfg fail");
    }

    for (i = 0; i < var->nodes_cfg_table->node_cnt; i++)
    {
        node_cfg_t *node_cfg = &var->nodes_cfg_table->node[i];
        if (node_cfg->port == BLE)
        {
            cJSON *ext = cJSON_Parse(node_cfg->ext_data);
            char mode[16] = {0};

            GET_JSON_VALUE_STRING(ext, "mode", mode);

            if (strcmp(mode, "slave") == 0)
            {
                slave_cfg->dev_cnt++;
            }
            else if (strcmp(mode, "master") == 0)
            {
                server_cfg->enable = true;
                adv_cfg->enable = true;
                adv_cfg->type = "peripheral";
            }
            else if (strcmp(mode, "master_slave") == 0)
            {
                slave_cfg->dev_cnt++;
                server_cfg->enable = true;
                adv_cfg->enable = true;
                adv_cfg->type = "peripheral";
            }
            else
            {
                dy_syslog(LOG_DEBUG, "not supported mode:%s\n", mode);
            }
            cJSON_Delete(ext);
        }
    }

    if (slave_cfg->dev_cnt > 0)
    {
        slave_cfg->slave = calloc(slave_cfg->dev_cnt, sizeof(ble_slave_dev_t));
        int index = 0;
        for (i = 0; i < var->nodes_cfg_table->node_cnt; i++)
        {
            node_cfg_t *node_cfg = &var->nodes_cfg_table->node[i];
            if (node_cfg->port == BLE)
            {
                cJSON *ext = cJSON_Parse(node_cfg->ext_data);
                char mode[16] = {0};
                char *addr;
                char *type;
                GET_JSON_VALUE_STRING(ext, "mode", mode);
                dy_syslog(LOG_DEBUG, "mode:%s\n", mode);
                if (strcmp(mode, "slave") == 0 || strcmp(mode, "master_slave") == 0)
                {
                    ble_slave_dev_t *slave = &slave_cfg->slave[index];
                    index++;
                    GET_JSON_VALUE_STRING(ext, "mode", mode);
                    GET_JSON_VALUE_DY_STRING(ext, "addr", addr);
                    GET_JSON_VALUE_DY_STRING(ext, "addr_type", type);
                    slave->addr = addr;
                    slave->AddressType = type;
                    slave->SN = node_cfg->sn;
                }
                cJSON_Delete(ext);
            }
        }
    }

    if (server_cfg->enable)
    {
        /*
        {
            "mode": "master_slave",
            "addr": "E0:51:24:CC:53:A3",
            "addr_type": "public",
            "Services": [{
                "uuid": "01ff0100-ba5e-f4ee-5ca1-eb1e5e4b1ce0",
                "Characteristics": [{
                    "uuid": "01ff0101-ba5e-f4ee-5ca1-eb1e5e4b1ce0",
                    "Flags": "write-without-response,read"
                }]
            }]
        }
        */
        for (i = 0; i < var->nodes_cfg_table->node_cnt; i++)
        {
            node_cfg_t *node_cfg = &var->nodes_cfg_table->node[i];
            if (node_cfg->port == BLE)
            {
                cJSON *ext = cJSON_Parse(node_cfg->ext_data);
                char mode[16] = {0};
                GET_JSON_VALUE_STRING(ext, "mode", mode);
                if (strcmp(mode, "master") == 0 || strcmp(mode, "master_slave") == 0)
                {
                    cJSON *services = cJSON_GetObjectItem(ext, "Services");
                    if (!services)
                    {
                        cJSON_Delete(ext);
                        continue;
                    }

                    server_cfg->service_cnt = cJSON_GetArraySize(services);
                    if (server_cfg->service_cnt > 0)
                    {
                        int j = 0;
                        server_cfg->services = calloc(server_cfg->service_cnt, sizeof(ble_gatt_service_cfg_t));
                        for (j = 0; j < server_cfg->service_cnt; j++)
                        {
                            ble_gatt_service_cfg_t *service_cfg = &server_cfg->services[j];
                            cJSON *service = cJSON_GetArrayItem(services, j);
                            if (service)
                            {
                                GET_JSON_VALUE_DY_STRING(service, "uuid", service_cfg->uuid);
                                service_cfg->primary = true;
                                cJSON *chrcs = cJSON_GetObjectItem(service, "Characteristics");
                                service_cfg->num_char = cJSON_GetArraySize(chrcs);
                                service_cfg->chars = calloc(service_cfg->num_char, sizeof(ble_gatt_service_char_t));
                                int k = 0;
                                dy_syslog(LOG_DEBUG, "service_cfg->num_char:%d\n", service_cfg->num_char);

                                for (k = 0; k < service_cfg->num_char; k++)
                                {
                                    ble_gatt_service_char_t *chr_cfg = &service_cfg->chars[k];
                                    cJSON *chr = cJSON_GetArrayItem(chrcs, k);
                                    char *flags;

                                    GET_JSON_VALUE_DY_STRING(chr, "uuid", chr_cfg->uuid);
                                    GET_JSON_VALUE_DY_STRING(chr, "Flags", flags);
                                    chr_cfg->Flags = g_strsplit(flags, ",", -1);
                                }
                            }
                        }
                    }
                }
                cJSON_Delete(ext);
            }
        }
    }

    return true;
}
