// audio_output.h - Audio output interface for Lua sandbox
// Milestone 13: Safe audio playback with volume limits and concurrent sound management

#pragma once

#include <string>
#include <memory>
#include <functional>
#include <mutex>
#include <atomic>
#include <vector>
#include <unordered_map>

struct lua_State;

namespace mosis {

enum class AudioState {
    Playing,
    Paused,
    Stopped
};

struct PlaybackConfig {
    float volume = 1.0f;      // 0.0 to 1.0
    bool loop = false;
    float pitch = 1.0f;       // 0.5 to 2.0
    float pan = 0.0f;         // -1.0 (left) to 1.0 (right)
};

struct AudioData {
    std::vector<uint8_t> data;
    int sample_rate = 44100;
    int channels = 1;
    int bits_per_sample = 16;
};

class SoundPlayer {
public:
    using EndCallback = std::function<void()>;

    SoundPlayer(int id, const AudioData& audio, const PlaybackConfig& config);
    ~SoundPlayer();

    int GetId() const { return m_id; }
    AudioState GetState() const { return m_state; }
    float GetVolume() const { return m_volume; }
    bool IsLooping() const { return m_loop; }

    // Control
    void Play();
    void Pause();
    void Stop();
    void SetVolume(float volume);
    void SetPitch(float pitch);
    void SetPan(float pan);

    // Callback when playback ends
    void SetOnEnd(EndCallback cb) { m_on_end = std::move(cb); }

    // For mock mode - simulate playback completion
    void SimulateEnd();

    // Get playback position (0.0 to 1.0)
    float GetPosition() const { return m_position; }

private:
    int m_id;
    AudioData m_audio;
    std::atomic<AudioState> m_state{AudioState::Stopped};
    float m_volume = 1.0f;
    float m_pitch = 1.0f;
    float m_pan = 0.0f;
    bool m_loop = false;
    float m_position = 0.0f;
    EndCallback m_on_end;
    mutable std::mutex m_mutex;
};

class AudioOutputInterface {
public:
    AudioOutputInterface(const std::string& app_id);
    ~AudioOutputInterface();

    // Play a sound
    // Returns player on success, nullptr on failure (sets error)
    std::shared_ptr<SoundPlayer> Play(const AudioData& audio, const PlaybackConfig& config, std::string& error);

    // Stop a specific player
    void StopPlayer(int player_id);

    // Stop all sounds for this app
    void StopAll();

    // Get active player count
    size_t GetActivePlayerCount() const;

    // Get system volume (0.0 to 1.0)
    float GetSystemVolume() const { return m_system_volume; }

    // Set system volume (for testing)
    void SetSystemVolume(float volume);

    // Cleanup on app stop
    void Shutdown();

    // For testing
    void SetMockMode(bool enabled) { m_mock_mode = enabled; }
    bool IsMockMode() const { return m_mock_mode; }

    // Get player by ID
    std::shared_ptr<SoundPlayer> GetPlayer(int id);

private:
    std::string m_app_id;
    std::unordered_map<int, std::shared_ptr<SoundPlayer>> m_players;
    mutable std::mutex m_mutex;
    bool m_mock_mode = true;
    float m_system_volume = 1.0f;
    int m_next_player_id = 1;

    static constexpr int MAX_CONCURRENT_SOUNDS = 10;

    void CleanupStoppedPlayers();
};

// Register audio.* APIs as globals
void RegisterAudioAPI(lua_State* L, AudioOutputInterface* audio);

} // namespace mosis
