#ifndef VIDEO_DECODER_H
#define VIDEO_DECODER_H

#include <cstdint>
#include <cstddef>
#include <string>

// Video decoder using NDK MediaCodec API
// Decodes video files to YUV420 frames and writes to shared memory ring buffer
// for consumption by the HAL hook in the camera provider process.

namespace video_decoder {

// Shared memory ring buffer header
// This structure is placed at the beginning of the memfd shared memory region.
struct RingBufferHeader {
    uint32_t magic;           // 0xCAM2MAGC
    uint32_t version;         // Header version (1)
    uint32_t frame_count;     // Number of frame slots in ring buffer
    uint32_t frame_width;     // Decoded frame width
    uint32_t frame_height;    // Decoded frame height
    uint32_t frame_size;      // Size of one YUV420 frame (w * h * 3/2)
    uint32_t write_index;     // Atomic: next slot to write
    uint32_t read_index;      // Atomic: last slot read by consumer
    uint32_t sequence;        // Monotonically increasing frame counter
    uint32_t flags;           // Bit flags (bit 0: decoder running)
    uint64_t last_timestamp;  // Timestamp of last written frame (us)
    uint8_t  reserved[216];   // Padding to 256 bytes
};

static constexpr uint32_t RING_MAGIC = 0xCA22A61C;
static constexpr uint32_t RING_VERSION = 1;
static constexpr uint32_t RING_FRAME_COUNT = 4;
static constexpr uint32_t RING_HEADER_SIZE = 256;
static constexpr uint32_t FLAG_DECODER_RUNNING = 0x1;

// Calculate total shared memory size needed
inline size_t calc_shmem_size(uint32_t width, uint32_t height, uint32_t frame_count = RING_FRAME_COUNT) {
    size_t frame_size = (size_t)width * height * 3 / 2; // YUV420
    return RING_HEADER_SIZE + (frame_size * frame_count);
}

// Get pointer to frame slot in shared memory
inline uint8_t* get_frame_ptr(uint8_t* base, uint32_t index, uint32_t frame_size, uint32_t frame_count) {
    return base + RING_HEADER_SIZE + ((index % frame_count) * frame_size);
}

// Decoder state
struct DecoderState {
    std::string video_path;
    int32_t width;
    int32_t height;
    int32_t rotation;  // 0, 90, 180, 270
    bool loop;
    bool running;
    
    // Shared memory
    int shmem_fd;
    uint8_t* shmem_base;
    size_t shmem_size;
    RingBufferHeader* header;
    
    // Decoder thread
    pthread_t decoder_thread;
};

// Initialize the video decoder
// Returns 0 on success, negative on error
int init_decoder(const char* video_path, bool loop = true);

// Start the decoder thread
// Returns 0 on success
int start_decoder();

// Stop the decoder thread
void stop_decoder();

// Release decoder resources
void release_decoder();

// Get the shared memory fd (for passing to other processes)
// Returns -1 if not initialized
int get_shmem_fd();

// Get decoder state info
int get_decoder_width();
int get_decoder_height();
bool is_decoder_running();

// Write a YUV420 frame to the shared memory ring buffer
// Called internally by the decoder thread
// y_data, u_data, v_data: pointers to Y, U, V planes
// y_stride, uv_stride: stride of Y and UV planes
// width, height: frame dimensions
bool write_frame_to_ring(const uint8_t* y_data, const uint8_t* u_data, const uint8_t* v_data,
                         int y_stride, int uv_stride, int width, int height);

} // namespace video_decoder

#endif // VIDEO_DECODER_H
