/*
 * Copyright (c) 2000-2017 Samsung Electronics Co., Ltd All Rights Reserved
 *
 * PROPRIETARY/CONFIDENTIAL
 *
 * This software is the confidential and proprietary information of
 * SAMSUNG ELECTRONICS ("Confidential Information").
 * You shall not disclose such Confidential Information and shall
 * use it only in accordance with the terms of the license agreement
 * you entered into with SAMSUNG ELECTRONICS.
 * SAMSUNG make no representations or warranties about the suitability
 * of the software, either express or implied, including but not
 * limited to the implied warranties of merchantability, fitness for
 * a particular purpose, or non-infringement.
 * SAMSUNG shall not be liable for any damages suffered by licensee as
 * a result of using, modifying or distributing this software or its derivatives.
 */

/**
 * \file    wsm_transport.h
 * \brief   Header with all definitions for Transport Module. This file is
            an external part of Transport Module provided for Client Applications.
 * \author  Oleksii Chekanin (o.chekanin@samsung.com)
 * \author  Pavel Marusyk (p.marusik@samsung.com)
 * \author  Igor Savynikh (i.savynikh@samsung.com)
 * \version 0.1
 * \date    Created Mar 31, 2017 12:00 AM
 * \par     In Samsung Kyiv R&D Center (SRK) under a contract between
 * \par     LLC "Samsung Electronics Ukraine Company" (Kyiv, Ukraine) and
   \par     "Samsung Electronics Co", Ltd (Seoul, Republic of Korea)
 * \par     Copyright: (c) Samsung Electronics Co, Ltd 2013. All rights reserved.
 **/

#ifndef WSM_TRANSPORT_H
#define WSM_TRANSPORT_H

#include <stdbool.h>
#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif // ifdef __cplusplus

#define BLUETOOTH_MAC_ADDRESS_LEN 18
#define IP_ADDRESS_LEN 18

/*!
 * Length in bytes of string in a form of "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
 */
#define BLUETOOTH_UUID_128_LEN 37

#define BLUETOOTH_UUID_LEN 37
#define WIFI_MAC_ADDRESS_LEN 18

//!< Maximum possible value for transport operation timeout. In milliseconds.
#define TRANSPORT_OPERATION_MAX_TIMEOUT 300000

/*!
 * \brief Waiting for space in queue table timeout multiplier
 * This timeout should be less than send timeout
 */
#define WSM_QUEUE_SPACE_WAIT_MULTI  0.7

/*!
 * Default values for Connection operation. Time given in milliseconds.
 * \note see wsm_transport_operation_s
 */

/*!
 * Used with Bluetooth LE API.
 */

/*!
 * Default values for Connect operation for device acting as a Peripheral.
 * Time given in milliseconds.
 * \note see wsm_transport_operation_s
 */
#define DEFAULT_BT_LE_PERIPHERAL_CONNECTION_TIMEOUT TRANSPORT_OPERATION_MAX_TIMEOUT


/*!
 * Default values for Send operation. Time given in milliseconds.
 * \note see wsm_transport_operation_s
 */
#define DEFAULT_BT_ADAPTER_SEND_TIMEOUT 25000
#define DEFAULT_BT_LE_SEND_TIMEOUT 5000


/*!
 * Default values for Receive operation. Time given in milliseconds.
 * \note see wsm_transport_operation_s
 */
#define DEFAULT_BT_ADAPTER_RECEIVE_TIMEOUT 25000
#define DEFAULT_BT_LE_RECEIVE_TIMEOUT 10000

/*!
 * Timeout of the v3 packet receive during server initialization (v2 commitment +
 * v3 info packets sequence). For BLE this timeout was increased in twice to 400 msec
 */
#define SERVER_INIT_WAIT_FOR_V3_PACKET_TIMEOUT 400

/*!
 * This enumeration lists return codes for transport callbacks.
 * Each callback HAVE return one of these values as a result of own execution.
 * This value used to determine further action - whether to return value to
 * Client Application or try to call callback again.
 *
 * \note see structure wsm_transport_operation_t.
 */
typedef enum
{
    /*!
     * Successful execution of transport callback.
     */
    CALLBACK_RETURN_SUCCESS = 0,

    /*!
     * Callback failed, but another attempt to execute callback will be done,
     * until maximum allowed number of attempts will be reached.
     */
    CALLBACK_RETURN_ERR_RECOVERABLE = -1,

    /*!
     * Callback failed and there is no point to make one more call.
     */
    CALLBACK_RETURN_ERR_NONRECOVERABLE = -2,

    /*!
     * Only *receive() callback* can return this value. It means that socket
     * doesn't have incoming messages, thus it's impossible to read data.
     */
    CALLBACK_RETURN_ERR_NO_DATA_TO_READ = -3,

    /*!
     * Callback failed due to system error (OS-specific or protocol-specific error).
     */
    CALLBACK_RETURN_ERR_SYSTEM_ERROR = -4
} wsm_callback_result_t;

/*!
 * Enumeration for roles in WSM workflow.
 */
typedef enum
{
    WSM_SERVER = 1,
    WSM_CLIENT,

    WSM_IDENTITY_UNDEFINED
} wsm_identity_t;

/*!
 * Enumeration for supported transport protocols.
 */
typedef enum
{
    WSM_TRANSPORT_BLUETOOTH = 1,
    WSM_TRANSPORT_BLUETOOTH_LE,
    WSM_TRANSPORT_WIFI,
    WSM_TRANSPORT_WEAR,
    WSM_TRANSPORT_IP = 1000,

    WSM_TRANSPORT_UNDEFINED
} wsm_transport_type_t;

/*!
 * Structure with Bluetooth 128-bit UUID as a raw byte array.
 */
typedef struct wsm_uuid_128_s
{
    uint8_t value[BLUETOOTH_UUID_128_LEN];
} wsm_uuid_128_t;

/*!
 * Structure with values required to connect to device via Bluetooth protocol .
 */
typedef struct wsm_bluetooth_address_s
{
    uint8_t address[BLUETOOTH_MAC_ADDRESS_LEN];
} wsm_bluetooth_address_t;

/*!
 * This structure contains data specific for Bluetooth protocol and connection settings.
 * Bluetooth role defined by *identity* field in transport settings. All parameters are mandatory.
 */
typedef struct wsm_transport_bluetooth_s
{
    wsm_bluetooth_address_t remote; //!< MAC address of the remote device.

    wsm_uuid_128_t uuid; //!< Bluetooth Service's 128-bit UUID.
    int volatile client_socket;
} wsm_transport_bluetooth_t;

/*!
 * \struct wsm_transport_operation_s defines how WSM will work with blocking transport operation.
 * This structure contains:
 * * *timeout* - maximum time for transport operation attempt (in milliseconds)
 * * *attempts* - how many times to try perform operation in case of failure.
 *                Each attempt takes up to *timeout* milliseconds.
 */
typedef struct wsm_transport_operation_s
{
    uint32_t timeout_msec;
} wsm_transport_operation_t;

/*!
 * This structure contains data specific for WiFi protocol. NOT SUPPORTED!
 */
typedef struct wsm_transport_wifi_s
{
    uint8_t remote_address[WIFI_MAC_ADDRESS_LEN]; //!< MAC address of remote device
} wsm_transport_wifi_t;

/*!
 * This structure contains data specific for IP protocol.
 */
typedef struct wsm_transport_ip_s
{
    int volatile client_socket;
    int server_socket;
    uint8_t remote_address[IP_ADDRESS_LEN];
    int port;
} wsm_transport_ip_t;

/*!
 * Localhost address line
 */
#define LOCALHOST_IP_ADDRESS "127.0.0.1"

/*!
 * Wear OS transport layer specific data
 */
typedef struct wsm_transport_wear_s
{
    char *node_id;
    char *path;
} wsm_transport_wear_t;


typedef struct wsm_transport_settings_s wsm_transport_settings_t;

typedef struct wsm_receive_buffer_s
{
    uint8_t *data;
    size_t capacity;
    size_t requested_length;
    size_t actual_length;
} wsm_receive_buffer_t;

/*!
 * This structure contains pointers to callbacks used internally by Transport Module.
 */
typedef struct wsm_transport_callbacks_s
{
    struct
    {
        /*!
         * This function does all initialiazation. Called once and before open connection!
         */
        int32_t (*init)(wsm_transport_settings_t *settings, WSM_SESSION_ID session_id); //!< callback for initialization.

        int32_t (*open)(wsm_transport_settings_t *settings, WSM_SESSION_ID session_id); //!< callback to open socket
        int32_t (*close)(wsm_transport_settings_t *settings, WSM_SESSION_ID session_id); //!< callback to close socket

        /*!
         * As this function finished connection between 2 devices is over.
         */
        int32_t (*destroy)(wsm_transport_settings_t *settings); //!< callback for shutdown
    } connection;

    struct
    {
        //!< callback to send data
        int32_t (*send)(const wsm_transport_settings_t *settings, const uint8_t *packet,
                        size_t packet_len);

        //!< callback to receive data
        int32_t (*receive)(const wsm_transport_settings_t *settings, wsm_receive_buffer_t *buffer);
    } packet;
} wsm_transport_callbacks_t;

/*!
 * \struct wsm_transport_settings_s used by transport part of WSM and can be initialized by Client Application.
 * This structure contains:
 * * *identity* to specify role in WSM workflow
 * * *type* to define transport protocol used by Transport Module;
 * * *socket* as a key part of device communication
 * * transport-specific data in *protocol* union;
 * * *callbacks* object contains pointers to functions doing all work
 */
struct wsm_transport_settings_s
{
    wsm_identity_t identity; //!< role in transport communication
    wsm_transport_type_t type; //!< Transport protocol type

    /*!
     * \brief Operation for accepting connection request from the remote device.
     * open() callback can wait for *connection.timeout* milliseconds if
     * attempt to establish connection failed and after that try again.
     * \note Optional parameter.
     */
    wsm_transport_operation_t connection;

    /*!
     * \brief Operation of sending data to the remote device.
     * Tizen SPP implementation can send at once less bytes, than requested.
     * In such situation send() callback can wait for *connection.timeout*
     * milliseconds and try to send remaining bytes. Asynchronous *send*
     * operation for Bluetooth LE can use these value to guarantee actuall
     * transmission to the remote device.
     * \note Optional parameter.
     */
    wsm_transport_operation_t send;

    /*!
     * \brief Operation for waiting incoming data from the remote device.
     * receive() callback can wait for *receive.timeout* milliseconds if no
     * data were received and try again up to *receive.attempts* attempts.
     * \note Optional parameter.
     */
    wsm_transport_operation_t receive;

    union
    {
        wsm_transport_bluetooth_t bluetooth; //!< Bluetooth-specific settings
        wsm_transport_wifi_t wifi; //!< WiFi-specific settings
        wsm_transport_ip_t ip; //!< IP-specific settings
        wsm_transport_wear_t wear; //!< Wear OS transport layer specific
    } protocol;

    wsm_transport_callbacks_t callbacks; //!< callbacks called by Transport Module

    /*!
     * Pointer for custom Client Application data required by callbacks.
     * Managed only by callbacks, not WSM internally.
     */
    void *user_data;
};

#ifdef __cplusplus
}
#endif // ifdef __cplusplus
#endif // WSM_TRANSPORT_H
