#pragma once

#include <cstdint>
#include <functional>
#include <string>
#include <vector>

namespace fgc {

// One captured frame, owning a copy of its pixel buffer (was image_store_8bit).
struct Frame {
    std::vector<uint8_t> data;
    uint32_t  width  = 0;
    uint32_t  height = 0;
    int       channels = 0;     // 1 (mono) or 3 (RGB)
    long long timestamp_ms = 0; // Unix epoch ms
    int       cam_id = 0;       // index into the configured camera list
};

// Live per-camera identity, sensor telemetry, and acquisition stats, for the
// expanded camera view. Populated by deviceInfo(); fields the source can't read
// are left at their defaults.
struct CameraDeviceInfo {
    std::string id;
    std::string model;
    std::string serial;
    bool        streaming = false;

    // Current frame geometry as delivered.
    uint32_t  width         = 0;
    uint32_t  height        = 0;
    long long payload_bytes = 0;

    // Live sensor telemetry (read from the camera, throttled).
    double exposure_us    = 0.0;
    double gain_db        = 0.0;
    double wb_red         = 0.0;
    double wb_blue        = 0.0;
    double temperature_c  = 0.0;
    double actual_fps     = 0.0;

    // Cumulative acquisition stats since the source was created.
    long long frames_delivered = 0;
    long long frames_dropped   = 0;  // incomplete/invalid deliveries
    long long restarts         = 0;  // stream restarts (restart-on-stall)
};

// Abstraction over the camera array. Implemented by VimbaCameraSource (Allied
// Vision Vimba X) and MockCameraSource (synthetic frames, no hardware).
//
// Completed frames are delivered to the callback set via setFrameCallback();
// the consumer (ImagePipeline) encodes and stores them.
class ICameraSource {
public:
    using FrameCallback = std::function<void(const Frame&)>;

    virtual ~ICameraSource() = default;

    virtual void open()  = 0;   // acquire/open cameras
    virtual void close() = 0;
    virtual void start() = 0;   // begin acquisition
    virtual void stop()  = 0;

    // Software-trigger a capture. Returns true on success.
    virtual bool trigger() = 0;

    // Optional: change the acquisition frame rate. Default no-op (e.g. mocks).
    virtual bool setFrameRate(double /*fps*/) { return false; }

    virtual void setFrameCallback(FrameCallback cb) = 0;

    // Number of cameras this source manages.
    virtual int cameraCount() const = 0;

    // Live identity/telemetry/stats per camera, for the expanded camera view.
    // Default: none. Implementations may refresh a throttled cache, so non-const.
    virtual std::vector<CameraDeviceInfo> deviceInfo() { return {}; }
};

}  // namespace fgc
