#ifndef _SR_NETDEV_CONN_H
#define _SR_NETDEV_CONN_H




#include "sr_stddef.h"
#include "sr_netdev.h"
#include "sr_osal.h"







#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */


#ifdef MOLINK_USING_NETCONN_OPS
#include "sr_my_port.h"
#include "mo_ipaddr.h"
/**
 ***********************************************************************************************************************
 * @enum        mo_netconn_stat_t
 *
 * @brief       molink module network connect state
 ***********************************************************************************************************************
 */
typedef enum mo_netconn_stat
{
    NETCONN_STAT_NULL = 0,    /* netconn has not been created */
    NETCONN_STAT_INIT,        /* netconn was created but not connected */
    NETCONN_STAT_CONNECT,     /* netconn connect OK*/
    NETCONN_STAT_CLOSED_WAIT, /* netconn was closed but all connect info were not deleted */
    NETCONN_STAT_UNDEFINED    /* netconn undefined status */
} mo_netconn_stat_t;

/**
 ***********************************************************************************************************************
 * @enum        mo_netconn_type_t
 *
 * @brief       molink module network connect type
 ***********************************************************************************************************************
 */
typedef enum mo_netconn_type
{
    NETCONN_TYPE_NULL = 0,
    NETCONN_TYPE_TCP,
    NETCONN_TYPE_UDP,
    NETCONN_TYPE_TCP_V6,
    NETCONN_TYPE_UDP_V6,
} mo_netconn_type_t;

/**
 ***********************************************************************************************************************
 * Used to inform the callback function about changes
 *
 * RCVPLUS events say: Safe to perform a potentially blocking call call once more.
 * They are counted in sockets - three RCVPLUS events for accept mbox means you are safe
 * to call netconn_accept 3 times without being blocked.
 * Same thing for receive mbox.
 *
 * RCVMINUS events say: Your call to to a possibly blocking function is "acknowledged".
 * Socket implementation decrements the counter.
 *
 * For TX, there is no need to count, its merely a flag. SENDPLUS means you may send something.
 * SENDPLUS occurs when enough data was delivered to peer so netconn_send() can be called again.
 * A SENDMINUS event occurs when the next call to a netconn_send() would be blocking.
 ***********************************************************************************************************************
 */
typedef enum mo_netconn_evt
{
    MO_NETCONN_EVT_RCVPLUS,
    MO_NETCONN_EVT_RCVMINUS,
    MO_NETCONN_EVT_SENDPLUS,
    MO_NETCONN_EVT_SENDMINUS,
    MO_NETCONN_EVT_ERROR
} mo_netconn_evt_t;

struct mo_netconn;

typedef void (*mo_netconn_evt_callback)(struct mo_netconn *netconn, mo_netconn_evt_t evt, uint16_t len);
typedef void (*mo_netconn_data_callback)(void *var, ip_addr_t addr, uint16_t port, char *data, os_size_t size);

/**
 ***********************************************************************************************************************
 * @struct      mo_netconn_t
 *
 * @brief       molink module network connect object
 ***********************************************************************************************************************
 */
typedef struct mo_netconn
{
#ifdef MOLINK_USING_SOCKETS_OPS
    int32_t                  socket_id;
    mo_netconn_evt_callback  evt_func;
    mo_netconn_data_callback data_func;
#endif
    int32_t connect_id;

    mo_netconn_stat_t stat;
    mo_netconn_type_t type;

    ip_addr_t remote_ip;
    uint16_t  remote_port;
    uint16_t  local_port;

    //os_msgqueue_id mq_id;
    void *mq_id;

} mo_netconn_t;

/**
 ***********************************************************************************************************************
 * @struct      mo_netconn_info_t
 *
 * @brief       struct that holds molink module netconn information
 ***********************************************************************************************************************
 */
typedef struct mo_netconn_info
{
    uint32_t            netconn_nums;
    const mo_netconn_t *netconn_array;
} mo_netconn_info_t;

/**
 ***********************************************************************************************************************
 * @struct      mo_netconn_msg_t
 *
 * @brief       struct that holds molink recv mq data information
 ***********************************************************************************************************************
 */
typedef struct mo_netconn_msg
{
    ip_addr_t addr;
    uint16_t  port;
    char     *data;
    uint32_t  data_len;
} mo_netconn_msg_t;

/**
 ***********************************************************************************************************************
 * @struct      mo_netconn_ops_t
 *
 * @brief       molink module network connect ops table
 ***********************************************************************************************************************
 */
typedef struct mo_netconn_ops
{
    mo_netconn_t *(*create)(SR_NETDEV_T *module, mo_netconn_type_t type);
    os_err_t (*destroy)(SR_NETDEV_T *module, mo_netconn_t *netconn);
    os_err_t (*connect)(SR_NETDEV_T *module, mo_netconn_t *netconn, ip_addr_t addr, uint16_t port);
    os_err_t (*bind)(SR_NETDEV_T *module, mo_netconn_t *netconn, ip_addr_t addr, uint16_t port);
    os_size_t (*sendto)(SR_NETDEV_T  *module,
                        mo_netconn_t *netconn,
                        ip_addr_t     remote_ip,
                        uint16_t      remote_port,
                        const char   *data,
                        os_size_t     size);
    os_size_t (*send)(SR_NETDEV_T *module, mo_netconn_t *netconn, const char *data, os_size_t size);
    os_err_t (*gethostbyname)(SR_NETDEV_T *module, const char *domain_name, ip_addr_t *addr);
    os_err_t (*get_info)(SR_NETDEV_T *module, mo_netconn_info_t *info);
} mo_netconn_ops_t;

mo_netconn_t *mo_netconn_create(SR_NETDEV_T *module, mo_netconn_type_t type);
os_err_t      mo_netconn_destroy(SR_NETDEV_T *module, mo_netconn_t *netconn);
os_err_t      mo_netconn_bind(SR_NETDEV_T *module, mo_netconn_t *netconn, ip_addr_t addr, uint16_t port);
os_err_t      mo_netconn_connect(SR_NETDEV_T *module, mo_netconn_t *netconn, ip_addr_t addr, uint16_t port);
os_size_t     mo_netconn_sendto(SR_NETDEV_T  *module,
                                mo_netconn_t *netconn,
                                ip_addr_t     remote_ip,
                                uint16_t      remote_port,
                                const char   *data,
                                os_size_t     size);
os_size_t     mo_netconn_send(SR_NETDEV_T *module, mo_netconn_t *netconn, const char *data, os_size_t size);
os_err_t      mo_netconn_recvfrom(SR_NETDEV_T  *module,
                                  mo_netconn_t *netconn,
                                  void        **data,
                                  os_size_t    *size,
                                  ip_addr_t    *addr,
                                  uint16_t     *port,
                                  os_tick_t     timeout);
os_err_t      mo_netconn_gethostbyname(SR_NETDEV_T *module, const char *domain_name, ip_addr_t *addr);

/**
 ***********************************************************************************************************************
 * @note These functions are called by the molink component
 ***********************************************************************************************************************
 */
os_err_t mo_netconn_get_info(SR_NETDEV_T *module, mo_netconn_info_t *info);
void     mo_netconn_pasv_close_notice(mo_netconn_t *netconn);
void mo_wifi_netconn_data_recv_notice(mo_netconn_t *netconn, ip_addr_t addr, uint16_t port, char *data, os_size_t size);
void mo_netconn_data_recv_notice(mo_netconn_t *netconn, char *data, os_size_t size);

//void mo_netconn_mq_destroy(os_msgqueue_id mq_id);
void mo_netconn_mq_destroy(void *mq_id);

#endif /* MOLINK_USING_NETCONN_OPS */





#ifdef SR_NETDEV_USE_CTWING

/**
 * @brief CTW事件枚举
 * 
 */
typedef enum CTW_EVT
{
    CTW_EVT_RECV = 0,            /*!< CTW M2M数据接收 */
  
}CTW_EVT_E;



typedef struct CTW_CONN_PARAM
{
    char *ip;
    uint16_t port;

}CTW_CONN_PARAM_T;


/**  
* @brief 网卡运维事件回调函数类型
*   
* @param[in] evt   CTW事件 
* @param[in] data  事件数据 
* @param[in] dLen  事件数据的长度 
* @param[in] args  用户自定义参数
*  
* @return 无 
*/
typedef void (*CtwEvtCb)(CTW_EVT_E evt,uint8_t *data,uint16_t dLen, void *args);


/**
 * @brief netdev 底层运维操作函数集合
 */
typedef struct SR_NETDEV_CTW_OPS 
{
    int (*ctw_connect)(SR_NETDEV_T *dev,CTW_CONN_PARAM_T *param);
    int (*ctw_send)(SR_NETDEV_T *dev,uint8_t *data,uint16_t dLen);
} SR_NETDEV_CTW_OPS_T;



int _HalNetCtwConnect(SR_NETDEV_T *dev,CTW_CONN_PARAM_T *param);
int _HalNetCtwSend(SR_NETDEV_T *dev,uint8_t *data,uint16_t dLen);



int SR_HalNetCtwSetEvtCb(SR_NETDEV_T *dev,CtwEvtCb cb,void *args);
#define SR_HalNetCtwConnect(dev,params)  SR_CT_CHILD(_HalNetCtwConnect(dev,params))
#define SR_HalNetCtwSend(dev,data,dLen)  SR_CT_CHILD(_HalNetCtwSend(dev,data,dLen))


#endif






#ifdef __cplusplus
}
#endif /* __cplusplus */



#endif /* __MO_NETCONN_H__ */
