#ifndef K230_VENC_H
#define K230_VENC_H

#include <cstdint>
#include <vector>
#include <stdexcept>
#include <cstring>
#include "k_venc_comm.h"

/**
 * @brief Enumeration of supported video encoder types
 * Defines the different video compression standards that can be used
 */
enum EncoderType {
    VENC_UNKNOWN, ///< Unknown/unsupported codec type
    VENC_H264,   ///< H.264 / AVC (Advanced Video Coding) standard
    VENC_H265,   ///< H.265 / HEVC (High Efficiency Video Coding) standard
    VENC_JPEG    ///< JPEG (Joint Photographic Experts Group) image compression standard
};

// 编码数据包
struct EncodedPacket {
    void* data;             ///< Pointer to the encoded data buffer (virtual address)
    uint64_t phys_addr;     ///< Physical address of the encoded data
    uint32_t size;          ///< Size of the encoded data in bytes
    k_venc_pack_type type;  ///< Type of the encoded packet (e.g., I-frame, P-frame, reference k_venc_comm.h)
    uint64_t pts;           ///< Presentation time stamp in microseconds
};

/**
 * @brief Structure containing encoded video stream data
 * Holds the compressed video data along with metadata required for proper playback/processing
 */
typedef struct tag_EncodedStream {
    std::vector<EncodedPacket> packets;
    uint32_t packet_count;
} EncodedStream;

/**
 * @brief Configuration parameters for initializing a video encoder
 * Contains all necessary settings to set up encoding parameters and behavior
 */
struct EncoderConfig {
    EncoderType type;               ///< Target encoding standard (H264/H265/JPEG)
    k_venc_profile profile;         ///< Encoding profile (defines feature set, reference k_venc_comm.h)
    uint32_t width;                 ///< Width of the output video stream in pixels
    uint32_t height;                ///< Height of the output video stream in pixels
    uint32_t bitrate;               ///< Target bitrate in kbps (kilobits per second)
    uint32_t gop;                   ///< Group of Pictures size (number of frames between I-frames)
    uint32_t src_fps;               ///< Frame rate of the input source (frames per second)
    uint32_t dst_fps;               ///< Target frame rate of the encoded output
    uint32_t jpeg_quality;          ///< Quality level for JPEG encoding (0-100, higher = better quality)
    uint32_t output_buffers;        ///< attach venc pool vb count

    /**
     * @brief Constructor for EncoderConfig with default values
     * @param enc_type Target encoder type (H264/H265/JPEG)
     * @param prof Encoding profile
     * @param w Output stream width in pixels
     * @param h Output stream height in pixels
     * @param buf_num Number of output buffers (default: 4)
     * @param br Target bitrate in kbps (default: 2048)
     * @param g GOP size (default: 30)
     * @param sfps Source input frame rate (default: 30)
     * @param dfps Destination output frame rate (default: 30)
     * @param jq JPEG quality (default: 45, only used for JPEG)
     */
    EncoderConfig(EncoderType enc_type, k_venc_profile prof, uint32_t w, uint32_t h,
                  uint32_t buf_num = 4, uint32_t br = 2048, uint32_t g = 30,
                  uint32_t sfps = 30, uint32_t dfps = 30,
                  uint32_t jq = 45);
};

/**
 * @brief Video encoder class managing a single encoding channel
 * Provides complete lifecycle management and operation of a video encoding instance,
 * handling frame input, encoding processing, and encoded data output
 */
class VideoEncoder {
public:
    /**
     * @brief Constructor initializing with encoder configuration
     * @param config Encoder configuration parameters
     */
    VideoEncoder(const EncoderConfig& config);

    /**
     * @brief Destructor cleaning up encoder resources
     */
    ~VideoEncoder();

    /**
     * @brief Creates and initializes the encoder instance
     * Allocates necessary resources and sets up encoding parameters
     * @return 0 on success, non-zero error code on failure
     */
    int create();

    /**
     * @brief Starts the encoder operation
     * Puts the encoder into active state ready to process input frames
     * @return 0 on success, non-zero error code on failure
     */
    int start();

    /**
     * @brief Sends a raw video frame to the encoder for processing
     * @param frame Pointer to the raw video frame information
     * @param timeout Maximum time to wait for frame submission in milliseconds (default: 1000)
     * @return 0 on success, non-zero error code on failure
     */
    int send_frame(k_video_frame_info* frame, int timeout = 1000);

    /**
     * @brief Retrieves encoded stream data from the encoder
     * @param stream Output parameter to store the encoded stream data
     * @param timeout Maximum time to wait for available stream data in milliseconds (default: 1000)
     * @return 0 on success, non-zero error code on failure
     */
    int get_stream(EncodedStream& stream, int timeout = 1000);

    /**
     * @brief Releases the encoded stream buffer back to the encoder
     * Must be called after processing the stream data to avoid memory leaks
     * @param stream The encoded stream to release
     * @return 0 on success, non-zero error code on failure
     */
    int release_stream(EncodedStream& stream);

    /**
     * @brief Stops the encoder operation
     * Pauses encoding processing while preserving allocated resources
     * @return 0 on success, non-zero error code on failure
     */
    int stop();

    /**
     * @brief Destroys the encoder instance
     * Releases all allocated resources and cleans up the encoder
     * @return 0 on success, non-zero error code on failure
     */
    int destroy();

    /**
     * @brief Gets the hardware channel ID of the encoder
     * @return Channel ID as an unsigned 32-bit integer
     */
    int get_channel_id() const { return channel_id_; }

private:
    /**
     * @brief Enumeration of possible encoder states
     * Represents the lifecycle stages of the encoder instance
     */
    enum EncoderState {
        CREATED,    ///< Encoder created but not started
        STARTED,    ///< Encoder actively processing frames
        STOPPED,    ///< Encoder stopped but not destroyed
        DESTROYED   ///< Encoder destroyed and resources released
    };

    k_u32 channel_id_;              ///< Hardware channel identifier for the encoder
    EncoderState state_;            ///< Current operational state of the encoder
    EncoderConfig config_;          ///< Stored encoder configuration parameters
    k_venc_stream output_;          ///< Internal structure for encoded stream data
    k_venc_pack  venc_pack_[30];    ///< Internal structure for encoder packet information
    k_u32 private_pool_id_;         ///< Identifier for internal buffer pool

    /**
     * @brief Sets up output buffers for encoded data
     * Allocates and initializes buffer pool for storing encoded results
     * @return 0 on success, non-zero error code on failure
     */
    int _setup_output_buffers();

    /**
     * @brief Creates encoder channel attributes
     * Populates hardware-specific encoder attributes based on configuration
     * @param venc_attr Output parameter to store the created attributes
     */
    void _create_encoder_attributes(k_venc_chn_attr& venc_attr);
};

#endif // K230_VENC_H