#include "device.h"
#include "config/board_config.h"

/**
 * @brief PC OR 手机数据内部接口 
 *
 * @param port 由对应的驱动提供的绑定接口获得的句柄
 * @param type 对应的数据接口类型
 * @retval 0 成功
 */
static uint8_t pc_device_choice_inside(device_t *port, uint8_t type, uint8_t connect);

uint8_t device_init(device_t *port)
{
    uint8_t res = DEVICE_OK;
#if UART_ENABLE
    res = uart_init(&port->init_device);
    if(res)
    {
        return DEVICE_UART_ERROR;
    }
#endif
#if BLE_ENABLE
    res = ble_init(&port->init_device);
    if(res)
    {
        return DEVICE_BLE_ERROR;
    }
#endif
#if WIFI_ENABLE
    res = wifi_init(&port->init_device);
    if(res)
    {
        return DEVICE_WIFI_ERROR;
    }
#endif
    //默认选择串口
    res = embedded_device_choice(port, DATA_PORT_TYPE_UART);
    if(res == DEVICE_EMBEDDED_ERROR)
    {
        SYS_LOG_ERR("embedded device choice error");
    }
    //默认BLE模式
    res = pc_device_choice_inside(port, DATA_PORT_TYPE_BLE_VAL, DISCONNECT);
    if(res == DEVICE_PC_ERROR)
    {
        SYS_LOG_ERR("pc device choice error");
    }
    SYS_LOG_INF("device init success");
    return DEVICE_OK;
}
uint8_t uart_init(init_device_t *port)
{
    // port->uart_port = sb_uart_port_bind(g_cfg_board->uart_fc.id, g_cfg_board->uart_fc.br, g_cfg_board->uart_fc.pin_txd.pin, g_cfg_board->uart_fc.pin_rxd.pin, g_cfg_board->uart_fc.irq_prior, 1024, 0, NULL);
    port->uart_port = sb_uart_port_bind(1, 115200, 21, 20, 21, 1024, 0, NULL);

    if(port->uart_port == NULL)
    {
        SYS_LOG_WRN("uart init error");
        return 1;
    }
    if(sb_data_port_start(port->uart_port))
    {
        SYS_LOG_WRN("uart start error");
        return 1;
    }
    return DEVICE_OK;
}
// 蓝牙连接回调函数
static void ble_server_connect_handler(ble_server_status_t status)
{
    // 处理连接状态，例如：
    if (status == BLE_SERVER_STATUS_CONNECTED) {
        uint8_t res = pc_device_choice_inside(NULL, DATA_PORT_TYPE_BLE_VAL, CONNECT_BLE);
        if(res == DEVICE_PC_ERROR){
        }
        SYS_LOG_INF("ble Connected");
    } else if(status == BLE_SERVER_STATUS_DISCONNECTED){
        uint8_t res = pc_device_choice_inside(NULL, DATA_PORT_TYPE_BLE_VAL, DISCONNECT);
        if(res == DEVICE_PC_ERROR){
        }
        SYS_LOG_INF("ble dis Connected");
        // disconnected / other
    } else {
        SYS_LOG_INF("ble stop");
    }
}
uint8_t ble_init(init_device_t *port)
{
    ble_server_init_t ble_init_param = {
        .device_name = "Sertorf",                // 设备名
        .manufacturer_data = NULL, // 回调函数，生成 manufacturer[20]
        .connect_cb = ble_server_connect_handler,                           // 回调函数， NULL 值可用
    };
    //初始化参数
    sb_ble_server_port_init(&ble_init_param);

    port->ble_spp_server_cmd = ble_server_port_bind_cmd(0x2000, NULL);
    port->ble_spp_server_val = ble_server_port_bind_val(0x400, NULL);

    if(port->ble_spp_server_cmd == NULL || port->ble_spp_server_val == NULL)
    {
        SYS_LOG_WRN("ble init error");
        return 1;
    }
    if(sb_data_port_start(port->ble_spp_server_cmd))
    {
        SYS_LOG_WRN("ble cmd start error");
        return 1;
    }
    if(sb_data_port_start(port->ble_spp_server_val))
    {
        SYS_LOG_WRN("ble val start error");
        return 1;
    }

    return DEVICE_OK;
}

//WIFI连接回调函数
static void wifi_event_handler(bool is_connect, sb_data_port_t *port)
{
    //实现自动切换发送对象
    if(is_connect){
        uint8_t res = pc_device_choice_inside(NULL, DATA_PORT_TYPE_WIFI_TCP, CONNECT_WIFI_TCP);
        if(res == DEVICE_PC_ERROR)
        {
            SYS_LOG_ERR("wifi pc device choice error");
        }
        SYS_LOG_INF("wifi connect");
    }else{
        uint8_t res = pc_device_choice_inside(NULL, DATA_PORT_TYPE_WIFI_UDP, CONNECT_WIFI_UDP);
        if(res == DEVICE_PC_ERROR)
        {
            SYS_LOG_ERR("wifi pc device choice error");
        }
        SYS_LOG_INF("wifi disconnect");
    }
}
static void wifi_ap_connect_handler(wifi_ap_connect_status_t status, uint8_t connect_cnt)
{
    SYS_LOG_WRN("wifi ap connect status %d %d", (int)status, (int)connect_cnt);
    //实现自动切换发送对象
    if((connect_cnt == 1 && status == WIFI_AP_CONNECT_GOT_STA)){
        uint8_t res = pc_device_choice_inside(NULL, DATA_PORT_TYPE_WIFI_UDP, CONNECT_WIFI_UDP);
        if(res == DEVICE_PC_ERROR)
        {
            SYS_LOG_ERR("wifi pc device choice error");
        }
        SYS_LOG_INF("wifi connect");
    }else{
        uint8_t res = pc_device_choice_inside(NULL, DATA_PORT_TYPE_WIFI_UDP, DISCONNECT);
        if(res == DEVICE_PC_ERROR)
        {
            SYS_LOG_ERR("wifi pc device choice error");
        }
        SYS_LOG_INF("wifi disconnect");
    }
}
static void wifi_sta_connect_handler(wifi_sta_connect_status_t status, uint8_t ip_v4[4])
{
    SYS_LOG_WRN("wifi ap connect status %d", (int)status);
    //实现自动切换发送对象
    if(status == WIFI_STA_CONNECT_GOT_IP){
        uint8_t res = pc_device_choice_inside(NULL, DATA_PORT_TYPE_WIFI_UDP, CONNECT_WIFI_UDP);
        if(res == DEVICE_PC_ERROR)
        {
            SYS_LOG_ERR("wifi pc device choice error");
        }
        SYS_LOG_INF("wifi connect");
    }else{
        uint8_t res = pc_device_choice_inside(NULL, DATA_PORT_TYPE_WIFI_UDP, DISCONNECT);
        if(res == DEVICE_PC_ERROR)
        {
            SYS_LOG_ERR("wifi pc device choice error");
        }
        SYS_LOG_INF("wifi disconnect");
    }
}
uint8_t wifi_init(init_device_t *port)
{
        /* 初始化 WIFI */
    wifi_init_t init_struct = {
        .ap = {
            .ssid = "Sertorf",    /**< SSID of soft-AP. If ssid_len field is 0, this must be a Null terminated string. Otherwise, length is set according to ssid_len. */
            .password = "", /**< Password of soft-AP. */
            .ip_v4 = {192, 168, 1, 1},
            .gw_v4 = {192, 168, 1, 1},
            .mask_v4 = {255, 255, 255, 0},
            .max_connection = 1,
            .connect_cb = wifi_ap_connect_handler,
        },
        .sta = {
#if 0
            .ssid = "KFXJ",
            .password = "Kfdx201*",
#else
            .ssid = "Sertorf_sta",
            .password = "12345678",
#endif
            .connect_cb = wifi_sta_connect_handler,
        },
    };
    wifi_netif_init(&init_struct);

    wifi_set_mode(WIFI_NETIF_MODE_AP);
    // wifi_set_mode(WIFI_NETIF_MODE_STA);

    // 初始化socket
    socket_inet_init();

    port->tcp_listen = socket_inet_server_listen_tcp(4278, 2, wifi_event_handler);

    socket_server_bind_t bind_param = {
        .rx_buf_size = 0x1000,
        .rx_event = NULL,
        .rx_resume_work = NULL,
    };

    port->wifi_tcp = socket_inet_server_bind_tcp(port->tcp_listen, &bind_param);

    port->wifi_udp = socket_inet_server_bind_udp(14550, &bind_param);

    if (port->wifi_tcp)
    {
        sb_data_port_start(port->wifi_tcp);
    }
    if (port->wifi_udp)
    {
        sb_data_port_start(port->wifi_udp);
    }
    
    wifi_mode_switch(port);

    wifi_start();
    return DEVICE_OK;
}
void wifi_mode_switch(init_device_t *port)
{
    static init_device_t* port_lat = NULL;
    static bool wifi_mode_flag = false;

    if(port_lat == NULL && port != NULL)
    {
        port_lat = port;
        return;
    }

    if (wifi_mode_flag)
    {
        wifi_mode_flag = false;
        wifi_set_mode(WIFI_NETIF_MODE_AP);
        port_lat->wifi_mode = WIFI_NETIF_MODE_AP;
        SYS_LOG_INF("wifi mode switch to ap");
    }
    else
    {
        wifi_mode_flag = true;
        wifi_set_mode(WIFI_NETIF_MODE_STA);
        port_lat->wifi_mode = WIFI_NETIF_MODE_STA;
        SYS_LOG_INF("wifi mode switch to sta");
    }
    wifi_start();
}
uint8_t embedded_device_choice(device_t *port, uint8_t type)
{
    //端口与PC一致
    if(port->pc_device_type == type)
    {
        SYS_LOG_WRN("pc Port consistency");
        return DEVICE_WRN_EMBEDDED_TYPE;
    }
    
    port->embedded_device_type = type;
    switch (port->embedded_device_type)
    {
        case DATA_PORT_TYPE_UART:
            port->embedded_device = port->init_device.uart_port;
            break;
        case DATA_PORT_TYPE_WIFI_TCP:
            port->embedded_device = port->init_device.wifi_tcp;
            break;
        case DATA_PORT_TYPE_WIFI_UDP:
            port->embedded_device = port->init_device.wifi_udp;
            break;
        case DATA_PORT_TYPE_BLE_CMD:
            port->embedded_device = port->init_device.ble_spp_server_cmd;
            break;
        case DATA_PORT_TYPE_BLE_VAL:
            port->embedded_device = port->init_device.ble_spp_server_val;
            break;
        default:
            break;
    }

    if(port->embedded_device == NULL)
    {
        SYS_LOG_WRN("embedded device choice error");
        return DEVICE_EMBEDDED_ERROR;
    }

    return DEVICE_OK;
}

int embedded_device_read(device_t *port, void *buffer, uint32_t length)
{
    return sb_data_port_read(port->embedded_device, buffer, length, 0);
}

int embedded_device_write(device_t *port, void *buffer, uint32_t length)
{
    return sb_data_port_write(port->embedded_device, buffer, length, 0);
}
uint32_t embedded_device_get_rx_length(device_t *port)
{
    return sb_data_port_get_rx_length(port->embedded_device);
}

static uint8_t pc_device_choice_inside(device_t *port, uint8_t type, uint8_t connect)
{
    static device_t* port_device_inside = NULL;
    SYS_LOG_WRN("pc_device_choice_inside type %d connect %d", type, connect);
    if(port != NULL && port_device_inside == NULL){
        SYS_LOG_INF("pc_device_choice_inside");
        pc_device_choice(port, type);
        port_device_inside = port;
        port_device_inside->connect_pc = connect;
    }else  if(port == NULL && port_device_inside != NULL && (port_device_inside->pc_device_type == type || connect != DISCONNECT)){
        pc_device_choice(port_device_inside, type);
        port_device_inside->connect_pc = connect;
    }
    return DEVICE_OK;
}
uint8_t pc_device_choice(device_t *port, uint8_t type)
{
    //端口与embedded一致
    if(port->embedded_device_type == type)
    {
        SYS_LOG_WRN("embedded Port consistency");
        return DEVICE_WRN_PC_TYPE;
    }
    
    port->pc_device_type = type;
    switch (port->pc_device_type)
    {
        case DATA_PORT_TYPE_UART:
            port->pc_device = port->init_device.uart_port;
            break;
        case DATA_PORT_TYPE_WIFI_TCP:
            port->pc_device = port->init_device.wifi_tcp;
            break;
        case DATA_PORT_TYPE_WIFI_UDP:
            port->pc_device = port->init_device.wifi_udp;
            break;
        case DATA_PORT_TYPE_BLE_CMD:
            port->pc_device = port->init_device.ble_spp_server_cmd;
            break;
        case DATA_PORT_TYPE_BLE_VAL:
            port->pc_device = port->init_device.ble_spp_server_val;
            break;
        default:
            break;
    }

    if(port->pc_device == NULL)
    {
        SYS_LOG_WRN("pc device choice error");
        return DEVICE_PC_ERROR;
    }

    return DEVICE_OK;
}
int pc_device_read(device_t *port, void *buffer, uint32_t length)
{
    return sb_data_port_read(port->pc_device, buffer, length, 0);
}

int pc_device_write(device_t *port, void *buffer, uint32_t length)
{
    if(port->connect_pc)
        return sb_data_port_write(port->pc_device, buffer, length, 0);
    
    return 0;
}
uint32_t pc_device_get_rx_length(device_t *port)
{
    return sb_data_port_get_rx_length(port->pc_device);
}