#include "common.h"



static gboolean register_characteristic(const char *chr_uuid,
                        const uint8_t *value, int vlen,
                        const char **props,
                        const char *desc_uuid,
                        const char **desc_props,
                        const char *service_path)
{   
    struct characteristic *chr;
    struct descriptor *desc;
    static int id = 1;
    
    chr = g_new0(struct characteristic, 1);
    chr->uuid = g_strdup(chr_uuid);
    chr->value = g_memdup(value, vlen);
    chr->vlen = vlen;
    chr->props = props;
    chr->service = g_strdup(service_path);
    chr->path = g_strdup_printf("%s/characteristic%d", service_path, id++);
    
    if (!g_dbus_register_interface(connection, chr->path, GATT_CHR_IFACE,
                    chr_methods, NULL, chr_properties,
                    chr, chr_iface_destroy)) {
        printf("Couldn't register characteristic interface\n");
        chr_iface_destroy(chr);
        return FALSE;
    }
    
    if (!desc_uuid)
        return TRUE;
                    
    desc = g_new0(struct descriptor, 1);
    desc->uuid = g_strdup(desc_uuid);
    desc->chr = chr;
    desc->props = desc_props;
    desc->path = g_strdup_printf("%s/descriptor%d", chr->path, id++);
    
    if (!g_dbus_register_interface(connection, desc->path,
                    GATT_DESCRIPTOR_IFACE,
                    desc_methods, NULL, desc_properties,
                    desc, desc_iface_destroy)) {
        printf("Couldn't register descriptor interface\n");
        g_dbus_unregister_interface(connection, chr->path,
                            GATT_CHR_IFACE);
    
        desc_iface_destroy(desc);
        return FALSE;
    }
    
    return TRUE;
}



static void create_services(ble_gatt_service_cfg_t *service)
{
    char *service_path;
    uint8_t level = 0;

    service_path = register_service(service->uuid);
    if (!service_path)
        return;

    /* Add Alert Level Characteristic to Immediate Alert Service */
    if (!register_characteristic(ALERT_LEVEL_CHR_UUID,
                                 &level, sizeof(level),
                                 ias_alert_level_props,
                                 READ_WRITE_DESCRIPTOR_UUID,
                                 desc_props,
                                 service_path))
    {
        printf("Couldn't register Alert Level characteristic (IAS)\n");
        g_dbus_unregister_interface(connection, service_path,
                                    GATT_SERVICE_IFACE);
        g_free(service_path);
        return;
    }

    services = g_slist_prepend(services, service_path);
    printf("Registered service: %s\n", service_path);
}


static void populate_service_one(struct server *server, ble_gatt_service_cfg_t *service)
{
	bt_uuid_t uuid;
	struct gatt_db_attribute *serv_att, *hr_msrmt, *body;
	int i;

	/* Add Service */
	serv_att = gatt_db_add_service(server->db, &service->uuid, service->primary, service->num_handles);

	for (i = 0; i < service->num_char; i++)
	{
		ble_gatt_service_char_t *chr = &service->chars[i];
		gatt_db_service_add_characteristic(serv_att, &chr->uuid,
										   chr->permissions,
										   chr->properties,
										   ble_common_read_cb, ble_common_write_cb, chr);
		int j = 0;

		for (j = 0; j < chr->num_desc; j++)
		{
			ble_gatt_service_desc_t *desc = &chr->desc[j];
			gatt_db_service_add_descriptor(serv_att, &desc->uuid,
										   desc->permissions,
										   ble_common_desc_read_cb,
										   ble_common_desc_write_cb, desc);
		}
	}

	gatt_db_service_set_active(serv_att, true);
}


bool start_gatt_services(ble_var_t *var, ble_dev_t *dev)
{
    ble_gatt_server_cfg_t *server_cfg;
    server_cfg = &dev->server_cfg;
    for (i = 0; i < server_cfg->service_cnt; i++)
    {
        ble_gatt_service_cfg_t *service = &server_cfg->services[i];
        create_services(service);
    }
}