#ifndef __MOZEN_TUNNEL_H
#define __MOZEN_TUNNEL_H

#include <stdint.h>
#include <stdbool.h>
#include "mozen_protocol.h"

// --- Tunnel Protocol Definitions ---

#define MOZEN_TUNNEL_COMMAND_ID     0xFB  // Tunnel command ID

typedef enum 
{
    TUNNEL_TYPE_HANDSHAKE      = 0x01, // Handshake request
    TUNNEL_TYPE_DATA_TRANSFER  = 0x02, // Data transfer
    TUNNEL_TYPE_RESPONSE       = 0xFF, // Special type for responses
} mozen_tunnel_type_t;

#pragma pack(1)
// 隧道协议头定义
typedef struct {
    uint8_t tunnel_type;
    uint8_t target_cmd;
} mozen_tunnel_header_t;

// 隧道握手请求结构体
typedef struct {
    mozen_tunnel_header_t header;
    uint32_t total_data_length;
    uint16_t total_packets;
} mozen_tunnel_handshake_req_t;

// 隧道数据包结构体
typedef struct {
    mozen_tunnel_header_t header;
    uint16_t status; // 'ok' or 'NG'
    uint16_t mtu;
} mozen_tunnel_handshake_res_t;

// 隧道数据传输包结构体
typedef struct {
    mozen_tunnel_header_t header;
    uint16_t packet_index;
    uint8_t  data_chunk[]; // Flexible array member for data
} mozen_tunnel_data_t;

// 隧道响应结构体
typedef struct {
    mozen_tunnel_header_t header;
    uint16_t status; // 'ok' or 'NG'
} mozen_tunnel_response_t;
#pragma pack()

// --- Tunnel Context and Callbacks ---

/**
 * @brief Callback for starting a stream write.
 * @param context User context.
 * @param target_cmd The command indicating the stream target.
 * @param first_chunk_data The first chunk of data, useful for analyzing sub-headers.
 * @param chunk_len Length of the first chunk.
 * @return True if streaming can begin, false to reject.
 */
typedef bool (*mozen_tunnel_on_stream_start_t)(void *context, uint8_t target_cmd, const uint8_t *first_chunk_data, uint16_t chunk_len);

/**
 * @brief Callback for continuing a stream write.
 * @param context User context.
 * @param data Chunk data.
 * @param len Chunk length.
 * @return True if chunk accepted, false to abort.
 */
typedef bool (*mozen_tunnel_on_stream_data_t)(void *context, const uint8_t *data, uint16_t len);

/**
 * @brief Callback for finishing a stream write.
 * @param context User context.
 * @param success True if the transfer completed successfully, false if aborted.
 */
typedef void (*mozen_tunnel_on_stream_finish_t)(void *context, bool success);

typedef struct 
{
    bool     is_active;
    uint8_t  target_cmd;
    uint32_t total_data_len;
    uint16_t total_packets;
    uint16_t next_packet_index;
    uint32_t received_data_len;
    
    // Config
    uint16_t mtu; // Max packet size
    mozen_protocol_t *prot; // For sending ACKs
    void *user_context; // For callbacks

    // Callbacks
    mozen_tunnel_on_stream_start_t on_start;
    mozen_tunnel_on_stream_data_t on_data;
    mozen_tunnel_on_stream_finish_t on_finish;
} mozen_tunnel_t;

// --- API ---

void mozen_tunnel_init(mozen_tunnel_t *tunnel, mozen_protocol_t *prot, uint16_t mtu, void *user_context);

void mozen_tunnel_set_callbacks(mozen_tunnel_t *tunnel, 
                                mozen_tunnel_on_stream_start_t on_start,
                                mozen_tunnel_on_stream_data_t on_data,
                                mozen_tunnel_on_stream_finish_t on_finish);

void mozen_tunnel_handle_command(mozen_tunnel_t *tunnel, const uint8_t *data, uint16_t length);

#endif // __MOZEN_TUNNEL_H
