/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

#include <string.h>
#include "host/ble_eddystone.h"
#include "host/ble_hs_adv.h"
#include "ble_hs_priv.h"

#define BLE_EDDYSTONE_MAX_SVC_DATA_LEN  22
#define BLE_EDDYSTONE_SVC_DATA_BASE_SZ  3

#define BLE_EDDYSTONE_SERVICE_UUID      0xfeaa

#define BLE_EDDYSTONE_FRAME_TYPE_UID    0x00
#define BLE_EDDYSTONE_FRAME_TYPE_URL    0x10

static ble_uuid16_t ble_eddystone_uuids16[BLE_EDDYSTONE_MAX_UUIDS16 + 1];
static uint8_t ble_eddystone_svc_data[BLE_EDDYSTONE_MAX_SVC_DATA_LEN];

/**
 * Writes an eddystone header to the global service data buffer.
 *
 * @param frame_type                The eddystone frame type; one of the
 *                                      BLE_EDDYSTONE_FRAME_TYPE_[...] values.
 *
 * @return                          A pointer to where the service data payload
 *                                      should be written.
 */
static void *
ble_eddystone_set_svc_data_base(uint8_t frame_type)
{
    put_le16(ble_eddystone_svc_data, BLE_EDDYSTONE_SERVICE_UUID);
    ble_eddystone_svc_data[2] = frame_type;

    return ble_eddystone_svc_data + BLE_EDDYSTONE_SVC_DATA_BASE_SZ;
}

/**
 * Populates the supplied advertisement fields struct to represent an eddystone
 * advertisement.  Prior to calling this function, you must write the service
 * data header and payload using the ble_eddystone_set_svc_data_base()
 * function.
 *
 * @param adv_fields            The base advertisement fields to transform into
 *                                  an eddystone beacon.  All configured fields
 *                                  are preserved; you probably want to clear
 *                                  this struct before calling this function.
 * @param svc_data_len          The amount of data written to the global
 *                                  service data buffer.
 *
 * @return                      0 on success; BLE_HS_E... on failure.
 */
static int
ble_eddystone_set_adv_data_gen(struct ble_hs_adv_fields *adv_fields,
                               uint8_t svc_data_len)
{
    int rc;

    if (adv_fields->num_uuids16 > BLE_EDDYSTONE_MAX_UUIDS16) {
        return BLE_HS_EINVAL;
    }
    if (svc_data_len > BLE_EDDYSTONE_MAX_SVC_DATA_LEN) {
        return BLE_HS_EINVAL;
    }
    if (adv_fields->num_uuids16 > 0 && !adv_fields->uuids16_is_complete) {
        return BLE_HS_EINVAL;
    }
    if (adv_fields->svc_data_uuid16_len != 0) {
        return BLE_HS_EINVAL;
    }

    ble_eddystone_uuids16[0] =
        (ble_uuid16_t) BLE_UUID16_INIT(BLE_EDDYSTONE_SERVICE_UUID);
    memcpy(ble_eddystone_uuids16 + 1, adv_fields->uuids16,
           adv_fields->num_uuids16 * sizeof(ble_uuid16_t));
    adv_fields->uuids16 = ble_eddystone_uuids16;
    adv_fields->num_uuids16++;
    adv_fields->uuids16_is_complete = 1;

    adv_fields->svc_data_uuid16 = ble_eddystone_svc_data;
    adv_fields->svc_data_uuid16_len = svc_data_len +
                                      BLE_EDDYSTONE_SVC_DATA_BASE_SZ;

    rc = ble_gap_adv_set_fields(adv_fields);
    if (rc != 0) {
        return rc;
    }

    return 0;
}

int
ble_eddystone_set_adv_data_uid(struct ble_hs_adv_fields *adv_fields,
                               void *uid, int8_t measured_power)
{
    uint8_t *svc_data;
    int rc;

    /* Eddystone UUID and frame type (0). */
    svc_data = ble_eddystone_set_svc_data_base(BLE_EDDYSTONE_FRAME_TYPE_UID);

    /* Measured Power ranging data (Calibrated tx power at 0 meters). */
    if (measured_power < -100 || measured_power > 20) {
        return BLE_HS_EINVAL;
    }
    svc_data[0] = measured_power;

    /* UID. */
    memcpy(svc_data + 1, uid, 16);

    /* Reserved. */
    svc_data[17] = 0x00;
    svc_data[18] = 0x00;

    rc = ble_eddystone_set_adv_data_gen(adv_fields, 19);
    if (rc != 0) {
        return rc;
    }

    return 0;
}

int
ble_eddystone_set_adv_data_url(struct ble_hs_adv_fields *adv_fields,
                               uint8_t url_scheme, char *url_body,
                               uint8_t url_body_len, uint8_t url_suffix,
                               int8_t measured_power)
{
    uint8_t *svc_data;
    int url_len;
    int rc;

    url_len = url_body_len;
    if (url_suffix != BLE_EDDYSTONE_URL_SUFFIX_NONE) {
        url_len++;
    }
    if (url_len > BLE_EDDYSTONE_URL_MAX_LEN) {
        return BLE_HS_EINVAL;
    }

    svc_data = ble_eddystone_set_svc_data_base(BLE_EDDYSTONE_FRAME_TYPE_URL);

    /* Measured Power ranging data (Calibrated tx power at 0 meters). */
    if (measured_power < -100 || measured_power > 20) {
        return BLE_HS_EINVAL;
    }
    svc_data[0] = measured_power;

    svc_data[1] = url_scheme;
    memcpy(svc_data + 2, url_body, url_body_len);
    if (url_suffix != BLE_EDDYSTONE_URL_SUFFIX_NONE) {
        svc_data[2 + url_body_len] = url_suffix;
    }

    rc = ble_eddystone_set_adv_data_gen(adv_fields, url_len + 2);
    if (rc != 0) {
        return rc;
    }

    return 0;
}
