// sensor_interface.h - Sensor interface for Lua sandbox
// Milestone 15: Motion sensors with fingerprinting prevention
#pragma once

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

struct lua_State;

namespace mosis {

enum class SensorType {
    Accelerometer,    // Requires sensors.motion
    Gyroscope,        // Requires sensors.motion
    Magnetometer,     // Requires sensors.motion
    Proximity,        // Auto-granted
    AmbientLight      // Auto-granted
};

struct SensorData {
    double x = 0.0;           // Primary axis / value
    double y = 0.0;           // Secondary axis (if applicable)
    double z = 0.0;           // Tertiary axis (if applicable)
    int64_t timestamp = 0;    // Milliseconds since epoch
};

struct SensorOptions {
    int frequency = 60;       // Hz, capped at 60
};

class SensorSubscription {
public:
    using DataCallback = std::function<void(const SensorData&)>;

    SensorSubscription(int id, SensorType type, const SensorOptions& options);
    ~SensorSubscription();

    int GetId() const { return m_id; }
    SensorType GetType() const { return m_type; }
    bool IsActive() const { return m_active; }
    int GetFrequency() const { return m_frequency; }

    void Start();
    void Stop();

    void SetOnData(DataCallback cb) { m_on_data = std::move(cb); }

    // For mock mode - simulate sensor data
    void SimulateData(const SensorData& data);

private:
    int m_id;
    SensorType m_type;
    int m_frequency;
    std::atomic<bool> m_active{false};
    DataCallback m_on_data;
    mutable std::mutex m_mutex;
};

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

    // Check if app has motion sensor permission
    bool HasMotionPermission() const { return m_has_motion_permission; }
    void SetMotionPermission(bool granted) { m_has_motion_permission = granted; }

    // Subscribe to a sensor
    // Returns subscription on success, nullptr on failure
    std::shared_ptr<SensorSubscription> Subscribe(
        SensorType type,
        const SensorOptions& options,
        std::string& error
    );

    // Subscribe by sensor name
    std::shared_ptr<SensorSubscription> Subscribe(
        const std::string& sensor_name,
        const SensorOptions& options,
        std::string& error
    );

    // Stop a specific subscription
    void Unsubscribe(int subscription_id);

    // Stop all subscriptions for this app
    void UnsubscribeAll();

    // Get active subscription count
    size_t GetActiveSubscriptionCount() const;

    // Cleanup on app stop
    void Shutdown();

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

    // Get subscription by ID
    std::shared_ptr<SensorSubscription> GetSubscription(int id);

    // Check if sensor type requires permission
    static bool RequiresPermission(SensorType type);

    // Parse sensor name to type
    static bool ParseSensorType(const std::string& name, SensorType& out_type);

    // Get sensor name from type
    static const char* GetSensorName(SensorType type);

    // Apply precision reduction to prevent fingerprinting
    SensorData ApplyPrecision(const SensorData& data) const;

private:
    std::string m_app_id;
    std::unordered_map<int, std::shared_ptr<SensorSubscription>> m_subscriptions;
    mutable std::mutex m_mutex;
    bool m_mock_mode = true;
    bool m_has_motion_permission = false;
    int m_next_subscription_id = 1;

    static constexpr int MAX_SUBSCRIPTIONS = 10;
    static constexpr int MAX_FREQUENCY = 60;  // Hz

    void CleanupStoppedSubscriptions();
};

// Register sensors.* APIs as globals
void RegisterSensorAPI(lua_State* L, SensorInterface* sensors);

} // namespace mosis
