/**
 * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form, except as embedded into a Nordic
 *    Semiconductor ASA integrated circuit in a product or a software update for
 *    such product, must reproduce the above copyright notice, this list of
 *    conditions and the following disclaimer in the documentation and/or other
 *    materials provided with the distribution.
 *
 * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
 *    contributors may be used to endorse or promote products derived from this
 *    software without specific prior written permission.
 *
 * 4. This software, with or without modification, must only be used with a
 *    Nordic Semiconductor ASA integrated circuit.
 *
 * 5. Any software provided in binary form under this license must not be reverse
 *    engineered, decompiled, modified and/or disassembled.
 *
 * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */
/** @file
 *
 * @defgroup ble_ncfgs Node Configuration Service
 * @{
 * @ingroup iot_sdk_common
 * @brief Node Configuration Service module.
 *
 * @details The Node Configuration Service allows configuration of the node during commissioning.
 *          During initialization it adds the Node Configuration Service and the corresponding
 *          characteristics to the BLE GATT database. It decodes and checks the received values
 *          and then passes them to the parent module.
 */

#ifndef BLE_NODE_CFG_H__
#define BLE_NODE_CFG_H__

#include <stdint.h>
#include "ble.h"
#include "app_util.h"

#ifdef __cplusplus
extern "C" {
#endif

#define BLE_UUID_NODE_CFG_SERVICE         0x7799
#define BLE_UUID_NCFGS_SSID_CHAR          0x77A9
#define BLE_UUID_NCFGS_KEYS_STORE_CHAR    0x77B9
#define BLE_UUID_NCFGS_CTRLPT_CHAR        0x77C9

#define APP_GATTERR_NOT_CONFIGURED        BLE_GATT_STATUS_ATTERR_APP_BEGIN + 1                      /**< ATT Error: Node configuration incomplete. */
#define APP_GATTERR_UNKNOWN_OPCODE        BLE_GATT_STATUS_ATTERR_APP_BEGIN + 2                      /**< ATT Error: Unknown opcode. */
#define APP_GATTERR_INVALID_ATTR_VALUE    BLE_GATT_STATUS_ATTERR_APP_BEGIN + 3                      /**< ATT Error: Invalid attribute value. */

#define NCFGS_SSID_MIN_LEN                6                                                         /**< SSID minimum length. */
#define NCFGS_SSID_MAX_LEN                16                                                        /**< SSID maximum length. */
#define NCFGS_KEYS_MAX_LEN                16                                                        /**< Keys maximum length. */
#define NCFGS_IDENTITY_DATA_MAX_LEN       8                                                         /**< Identity data maximum length. */

#define NCFGS_CTRLP_OPCODE_LEN            1                                                         /**< Ctrlp: Opcode value length. */
#define NCFGS_CTRLP_DELAY_LEN             4                                                         /**< Ctrlp: Length of action delay value. */
#define NCFGS_CTRLP_DURATION_LEN          4                                                         /**< Ctrlp: Length of next mode duration value. */
#define NCFGS_CTRLP_STATE_ON_FAILURE_LEN  1                                                         /**< Ctrlp: Length of state-on-failure value. */

#define NCFGS_CTRLP_ALL_BUT_ID_DATA_LEN   (NCFGS_CTRLP_OPCODE_LEN   +        \
                                           NCFGS_CTRLP_DELAY_LEN    +        \
                                           NCFGS_CTRLP_DURATION_LEN +        \
                                           NCFGS_CTRLP_STATE_ON_FAILURE_LEN)                        /**< Ctrlp: Total length of all values except identity data. */
#define NCFGS_CTRLP_VALUE_LEN             (NCFGS_CTRLP_OPCODE_LEN           +  \
                                           NCFGS_CTRLP_DELAY_LEN            +  \
                                           NCFGS_CTRLP_DURATION_LEN         +  \
                                           NCFGS_CTRLP_STATE_ON_FAILURE_LEN +  \
                                           NCFGS_IDENTITY_DATA_MAX_LEN)                             /**< Ctrlp: Total length of all values. */

#define HTONL(val)  ((((uint32_t) (val) & 0xff000000) >> 24)  |  \
                     (((uint32_t) (val) & 0x00ff0000) >> 8)   |  \
                     (((uint32_t) (val) & 0x0000ff00) << 8)   |  \
                     (((uint32_t) (val) & 0x000000ff) << 24))

/**@brief Node Configuration Service control point opcode values. */
typedef enum
{
    NCFGS_OPCODE_GOTO_JOINING_MODE  = 0x01,
    NCFGS_OPCODE_GOTO_CONFIG_MODE   = 0x02,
    NCFGS_OPCODE_GOTO_IDENTITY_MODE = 0x03
} ble_ncfgs_opcode_t;

/**@brief Node Configuration Service configuration states. */
typedef enum
{
    NCFGS_STATE_IDLE               = 0x00,
    NCFGS_STATE_SSID_WRITTEN       = 0x01,
    NCFGS_STATE_KEYS_STORE_WRITTEN = 0x02
} ble_ncfgs_state_t;

/**@brief Node Configuration Service state-on-failure values. */
typedef enum
{
    NCFGS_SOF_NO_CHANGE   = 0x00,
    NCFGS_SOF_PWR_OFF     = 0x01,
    NCFGS_SOF_CONFIG_MODE = 0x02
} state_on_failure_t;

/**@brief Structure for storing keys received from the peer. */
typedef struct __attribute__ ((__packed__))
{
    uint8_t             keys_len;
    uint8_t             keys[NCFGS_KEYS_MAX_LEN];                    // Keys received from the router.
} keys_store_t;

/**@brief Structure for storing the SSID received from the peer. */
typedef struct __attribute__ ((__packed__))
{
    uint8_t             ssid_len;
    uint8_t             ssid[NCFGS_SSID_MAX_LEN];                    // SSID received from the router.
} ssid_store_t;

/**@brief Structure for storing the identity data from the peer. */
typedef struct __attribute__ ((__packed__))
{
    uint8_t             identity_data_len;
    uint8_t             identity_data[NCFGS_IDENTITY_DATA_MAX_LEN];  // Custom node identifier data.
} id_data_store_t;

/**@brief Structure for control point value. */
typedef struct __attribute__ ((__packed__))
{
    ble_ncfgs_opcode_t  opcode;                                // Mode to start.
    uint32_t            delay_sec;                             // Delay before entering >Opcode< mode.
    uint32_t            duration_sec;                          // General timeout for >Opcode< mode.
    state_on_failure_t  state_on_failure;                      // Mode to enter if >Opcode< mode fails (times out).
} ble_ncfgs_ctrlp_value_t;

/**@brief Structure for storing Node Configuration Service characteristic values. */
typedef struct __attribute__ ((__packed__))
{
    ble_ncfgs_ctrlp_value_t  ctrlp_value;
    ssid_store_t             ssid_from_router;                 // SSID received from the peer.
    keys_store_t             keys_from_router;                 // Keys received from the peer.
    id_data_store_t          id_data;                          // Identity data received from the peer.
} ble_ncfgs_data_t;

/**@brief Function for handling BLE events.
 *
 * @details This function must be called from the BLE stack event dispatcher
 *          to handle BLE events that are relevant for the Node Configuration Service module.
 *          It propagates an event to the parent layer if the Control Point characteristic
 *          was successfully written.
 *
 * @param[in] p_ble_evt BLE stack event.
 */
void ble_ncfgs_ble_evt_handler(const ble_evt_t * p_ble_evt);

/**@brief Node Configuration Service event handler type. */
typedef void (*ble_ncfgs_evt_handler_t) (ble_ncfgs_data_t * ncfgs_data);

/**@brief Function for initializing the Node Configuration Service module.
 *
 * @details Interface for the Commissioning module to create a GATT database to
 *          allow for node configuration.
 *
 * @param[in]    ble_ncfgs_cb    Function to be called in case of an error.
 *
 * @retval       NRF_SUCCESS     If initialization was successful. Otherwise, a propagated
 *                               error code is returned.
 *
 */
uint32_t ble_ncfgs_init(ble_ncfgs_evt_handler_t ble_ncfgs_cb);

#ifdef __cplusplus
}
#endif

#endif // BLE_NODE_CFG_H__

/** @} */
