#ifndef ODIN_NODEJS_ODINMEDIA_H
#define ODIN_NODEJS_ODINMEDIA_H

#include <napi.h>
#include <odin.h>
#include <vector>
#include <atomic>
#include <mutex>

class OdinRoomWrapper;

/**
 * OdinMediaWrapper handles encoding and transmitting audio data to the ODIN server.
 * 
 * This wrapper closely follows the core ODIN SDK pattern:
 * 1. Constructor creates encoder (odin_encoder_create)
 * 2. setMediaId() sets the server-assigned media ID
 * 3. sendAudioData() encodes samples and sends datagrams (odin_encoder_push/pop + odin_room_send_datagram)
 * 4. close() frees the encoder (odin_encoder_free)
 *
 * Usage workflow (from JavaScript):
 * 1. Wait for Joined event to receive available media_ids
 * 2. Create audio stream: media = room.createAudioStream(48000, 2)
 * 3. Set the server-assigned media ID: media.setMediaId(mediaIds[0])
 * 4. Push audio chunks: media.sendAudioData(chunk)  // 20ms chunks recommended
 * 5. When done: media.close()
 * 
 * Thread Safety:
 * The close() method sets _closed atomically before freeing resources.
 * All methods check _closed first to prevent use-after-free crashes.
 */
class OdinMediaWrapper : public Napi::ObjectWrap<OdinMediaWrapper> {
public:
    OdinMediaWrapper(const Napi::CallbackInfo& info);
    static Napi::Object Init(Napi::Env env, Napi::Object exports);
    static Napi::Value CreateNewItem(const Napi::CallbackInfo& info);
    static Napi::Object NewInstance(const std::vector<napi_value>& args);
    void Finalize(Napi::Env env) override;

private:
    static Napi::FunctionReference *constructor;

    // Room and encoder references
    OdinRoomWrapper* _roomWrapper;
    struct OdinEncoder* _encoder;
    uint32_t _sampleRate;
    int _numChannels;

    // Server-assigned media ID (received from Joined event)
    uint16_t _mediaId;
    
    // Closed state - once set, all operations are rejected to prevent use-after-free.
    // This is set BEFORE freeing resources in Close() to ensure thread safety.
    std::atomic<bool> _closed;
    
    // Mutex for protecting resource cleanup
    std::mutex _closeMutex;

    // Native methods exposed to JavaScript
    void Close(const Napi::CallbackInfo& info);
    void SendData(const Napi::CallbackInfo& info);
    void SetMediaId(const Napi::CallbackInfo& info);
    Napi::Value MediaId(const Napi::CallbackInfo& info);
};

#endif //ODIN_NODEJS_ODINMEDIA_H


