/*
 * 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_store.h"
#include "ble_hs_priv.h"

int
ble_store_read(int obj_type, const union ble_store_key *key,
               union ble_store_value *val)
{
    int rc;

    ble_hs_lock();

    if (ble_hs_cfg.store_read_cb == NULL) {
        rc = BLE_HS_ENOTSUP;
    } else {
        rc = ble_hs_cfg.store_read_cb(obj_type, key, val);
    }

    ble_hs_unlock();

    return rc;
}

int
ble_store_write(int obj_type, const union ble_store_value *val)
{
    int rc;

    if (ble_hs_cfg.store_write_cb == NULL) {
        return BLE_HS_ENOTSUP;
    }

    while (1) {
        ble_hs_lock();
        rc = ble_hs_cfg.store_write_cb(obj_type, val);
        ble_hs_unlock();

        switch (rc) {
        case 0:
            return 0;
        case BLE_HS_ESTORE_CAP:
            /* Record didn't fit.  Give the application the opportunity to free
             * up some space.
             */
            rc = ble_store_overflow_event(obj_type, val);
            if (rc != 0) {
                return rc;
            }

            /* Application made room for the record; try again. */
            break;

        default:
            return rc;
        }
    }
}

int
ble_store_delete(int obj_type, const union ble_store_key *key)
{
    int rc;

    ble_hs_lock();

    if (ble_hs_cfg.store_delete_cb == NULL) {
        rc = BLE_HS_ENOTSUP;
    } else {
        rc = ble_hs_cfg.store_delete_cb(obj_type, key);
    }

    ble_hs_unlock();

    return rc;
}

static int
ble_store_status(struct ble_store_status_event *event)
{
    int rc;

    BLE_HS_DBG_ASSERT(!ble_hs_locked_by_cur_task());

    if (ble_hs_cfg.store_status_cb == NULL) {
        rc = BLE_HS_ENOTSUP;
    } else {
        rc = ble_hs_cfg.store_status_cb(event, ble_hs_cfg.store_status_arg);
    }

    return rc;
}

int
ble_store_overflow_event(int obj_type, const union ble_store_value *value)
{
    struct ble_store_status_event event;

    event.event_code = BLE_STORE_EVENT_OVERFLOW;
    event.overflow.obj_type = obj_type;
    event.overflow.value = value;

    return ble_store_status(&event);
}

int
ble_store_full_event(int obj_type, uint16_t conn_handle)
{
    struct ble_store_status_event event;

    event.event_code = BLE_STORE_EVENT_FULL;
    event.full.obj_type = obj_type;
    event.full.conn_handle = conn_handle;

    return ble_store_status(&event);
}

int
ble_store_read_our_sec(const struct ble_store_key_sec *key_sec,
                       struct ble_store_value_sec *value_sec)
{
    const union ble_store_key *store_key;
    union ble_store_value *store_value;
    int rc;

    BLE_HS_DBG_ASSERT(key_sec->peer_addr.type == BLE_ADDR_PUBLIC ||
                      key_sec->peer_addr.type == BLE_ADDR_RANDOM ||
                      ble_addr_cmp(&key_sec->peer_addr, BLE_ADDR_ANY) == 0);

    store_key = (void *)key_sec;
    store_value = (void *)value_sec;
    rc = ble_store_read(BLE_STORE_OBJ_TYPE_OUR_SEC, store_key, store_value);
    return rc;
}

static int
ble_store_persist_sec(int obj_type,
                      const struct ble_store_value_sec *value_sec)
{
    union ble_store_value *store_value;
    int rc;

    BLE_HS_DBG_ASSERT(value_sec->peer_addr.type == BLE_ADDR_PUBLIC ||
                      value_sec->peer_addr.type == BLE_ADDR_RANDOM);
    BLE_HS_DBG_ASSERT(value_sec->ltk_present ||
                      value_sec->irk_present ||
                      value_sec->csrk_present);

    store_value = (void *)value_sec;
    rc = ble_store_write(obj_type, store_value);
    return rc;
}

int
ble_store_write_our_sec(const struct ble_store_value_sec *value_sec)
{
    int rc;

    rc = ble_store_persist_sec(BLE_STORE_OBJ_TYPE_OUR_SEC, value_sec);
    return rc;
}

int
ble_store_delete_our_sec(const struct ble_store_key_sec *key_sec)
{
    union ble_store_key *store_key;
    int rc;

    store_key = (void *)key_sec;
    rc = ble_store_delete(BLE_STORE_OBJ_TYPE_OUR_SEC, store_key);
    return rc;
}

int
ble_store_delete_peer_sec(const struct ble_store_key_sec *key_sec)
{
    union ble_store_key *store_key;
    int rc;

    store_key = (void *)key_sec;
    rc = ble_store_delete(BLE_STORE_OBJ_TYPE_PEER_SEC, store_key);
    return rc;
}

int
ble_store_read_peer_sec(const struct ble_store_key_sec *key_sec,
                        struct ble_store_value_sec *value_sec)
{
    union ble_store_value *store_value;
    union ble_store_key *store_key;
    int rc;

    BLE_HS_DBG_ASSERT(key_sec->peer_addr.type == BLE_ADDR_PUBLIC ||
                      key_sec->peer_addr.type == BLE_ADDR_RANDOM);

    store_key = (void *)key_sec;
    store_value = (void *)value_sec;
    rc = ble_store_read(BLE_STORE_OBJ_TYPE_PEER_SEC, store_key, store_value);

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

    return 0;
}

int
ble_store_write_peer_sec(const struct ble_store_value_sec *value_sec)
{
    int rc;

    rc = ble_store_persist_sec(BLE_STORE_OBJ_TYPE_PEER_SEC, value_sec);
    if (rc != 0) {
        return rc;
    }

    if (ble_addr_cmp(&value_sec->peer_addr, BLE_ADDR_ANY) &&
        value_sec->irk_present) {

        /* Write the peer IRK to the controller keycache
         * There is not much to do here if it fails */
        rc = ble_hs_pvcy_add_entry(value_sec->peer_addr.val,
                                          value_sec->peer_addr.type,
                                          value_sec->irk);
        if (rc != 0) {
            return rc;
        }
    }

    return 0;
}

int
ble_store_read_cccd(const struct ble_store_key_cccd *key,
                    struct ble_store_value_cccd *out_value)
{
    union ble_store_value *store_value;
    union ble_store_key *store_key;
    int rc;

    store_key = (void *)key;
    store_value = (void *)out_value;
    rc = ble_store_read(BLE_STORE_OBJ_TYPE_CCCD, store_key, store_value);
    return rc;
}

int
ble_store_write_cccd(const struct ble_store_value_cccd *value)
{
    union ble_store_value *store_value;
    int rc;

    store_value = (void *)value;
    rc = ble_store_write(BLE_STORE_OBJ_TYPE_CCCD, store_value);
    return rc;
}

int
ble_store_delete_cccd(const struct ble_store_key_cccd *key)
{
    union ble_store_key *store_key;
    int rc;

    store_key = (void *)key;
    rc = ble_store_delete(BLE_STORE_OBJ_TYPE_CCCD, store_key);
    return rc;
}

void
ble_store_key_from_value_cccd(struct ble_store_key_cccd *out_key,
                              const struct ble_store_value_cccd *value)
{
    out_key->peer_addr = value->peer_addr;
    out_key->chr_val_handle = value->chr_val_handle;
    out_key->idx = 0;
}

void
ble_store_key_from_value_sec(struct ble_store_key_sec *out_key,
                             const struct ble_store_value_sec *value)
{
    out_key->peer_addr = value->peer_addr;
    out_key->idx = 0;
}

void
ble_store_key_from_value(int obj_type,
                         union ble_store_key *out_key,
                         const union ble_store_value *value)
{
    switch (obj_type) {
    case BLE_STORE_OBJ_TYPE_OUR_SEC:
    case BLE_STORE_OBJ_TYPE_PEER_SEC:
        ble_store_key_from_value_sec(&out_key->sec, &value->sec);
        break;

    case BLE_STORE_OBJ_TYPE_CCCD:
        ble_store_key_from_value_cccd(&out_key->cccd, &value->cccd);
        break;

    default:
        BLE_HS_DBG_ASSERT(0);
        break;
    }
}

int
ble_store_iterate(int obj_type,
                  ble_store_iterator_fn *callback,
                  void *cookie)
{
    union ble_store_key key;
    union ble_store_value value;
    int idx = 0;
    uint8_t *pidx;
    int rc;

    /* a magic value to retrieve anything */
    memset(&key, 0, sizeof(key));
    switch(obj_type) {
    case BLE_STORE_OBJ_TYPE_PEER_SEC:
    case BLE_STORE_OBJ_TYPE_OUR_SEC:
        key.sec.peer_addr = *BLE_ADDR_ANY;
        pidx = &key.sec.idx;
        break;
    case BLE_STORE_OBJ_TYPE_CCCD:
        key.cccd.peer_addr = *BLE_ADDR_ANY;
        pidx = &key.cccd.idx;
        break;
    default:
        BLE_HS_DBG_ASSERT(0);
        return BLE_HS_EINVAL;
    }

    while (1) {
        *pidx = idx;
        rc = ble_store_read(obj_type, &key, &value);
        switch (rc) {
        case 0:
            if (callback != NULL) {
                rc = callback(obj_type, &value, cookie);
                if (rc != 0) {
                    /* User function indicates to stop iterating. */
                    return 0;
                }
            }
            break;

        case BLE_HS_ENOENT:
            /* No more entries. */
            return 0;

        default:
            /* Read error. */
            return rc;
        }

        idx++;
    }
}

/**
 * Deletes all objects from the BLE host store.
 *
 * @return                      0 on success; nonzero on failure.
 */
int
ble_store_clear(void)
{
    const uint8_t obj_types[] = {
        BLE_STORE_OBJ_TYPE_OUR_SEC,
        BLE_STORE_OBJ_TYPE_PEER_SEC,
        BLE_STORE_OBJ_TYPE_CCCD,
    };
    union ble_store_key key;
    int obj_type;
    int rc;
    unsigned int i;

    /* A zeroed key will always retrieve the first value. */
    memset(&key, 0, sizeof key);

    for (i = 0; i < sizeof obj_types / sizeof obj_types[0]; i++) {
        obj_type = obj_types[i];

        do {
            rc = ble_store_delete(obj_type, &key);
        } while (rc == 0);

        /* BLE_HS_ENOENT means we deleted everything. */
        if (rc != BLE_HS_ENOENT) {
            return rc;
        }
    }

    return 0;
}
