#pragma once

#include <pxr/usd/usd/stage.h>
#include <pxr/usd/usd/timeCode.h>
#include "IconManager.h"
#include <functional>

namespace UsdLayerManager {

/// Bottom-docked playback timeline.
///
/// Owns the current frame, playback state, and the Auto-Key toggle, and fires
/// OnTimeChanged whenever the time changes:
///   displayTime — the current frame; used for all reads/evaluation
///   editTime    — the current frame when Auto-Key is ON, otherwise Default()
///
/// Supports:
///   Loop         — playback wraps from end back to start (or vice-versa).
///   Bounce       — playback reverses direction at each boundary (ping-pong).
///   Rewind       — reverse-direction playback (m_reversed).
class TimelinePanel {
public:
    void SetStage(pxr::UsdStageRefPtr stage);
    void SetIconManager(IconManager* icons) { m_iconManager = icons; }

    /// Advance playback by deltaTime seconds; called once per app frame.
    void Update(float deltaTime);
    void Render();

    std::function<void(pxr::UsdTimeCode displayTime,
                       pxr::UsdTimeCode editTime)> OnTimeChanged;

    // ── Playblast ────────────────────────────────────────────────────────────
    struct PlayblastSettings {
        char   outputDir[512]  = "";
        char   filePrefix[128] = "playblast";
        int    startFrame      = 1;
        int    endFrame        = 100;
        int    captureWidth    = 1920;
        int    captureHeight   = 1080;
        bool   exportMovie     = true;   // encode directly to MP4 (libavcodec)
        bool   keepFrames      = false;  // also write BMP frames alongside movie
        double fps             = 24.0;   // filled from stage fps at capture start
    };

    bool                     IsPlayblasting()         const { return m_isPlayblasting;    }
    /// True on the frame immediately after playblast begins — the viewport has
    /// not yet rendered at the start time, so the first capture must be skipped.
    bool                     GetPlayblastSkipFirst()  const { return m_playblastSkipFirst; }
    void                     ClearPlayblastSkipFirst()      { m_playblastSkipFirst = false; }
    int                      GetPlayblastFrameIndex() const { return m_playblastFrameIdx;  }
    const PlayblastSettings& GetPlayblastSettings()   const { return m_playblastSettings;  }
    double                   GetFps()                 const { return m_fps;                }

    /// Step to the next capture frame. Returns false (and stops capture) when done.
    bool AdvancePlayblast();
    void AbortPlayblast();

    /// Drive the timeline from an external source (e.g. curve editor scrubbing).
    void SetCurrentFrameExternal(double frame);

    /// Callback set by Application so the dialog can open a native folder picker.
    std::function<std::string()> OnBrowseFolder;

private:
    /// Clamp to [startFrame, endFrame]; fires OnTimeChanged when the frame changes.
    void SetCurrentFrame(double frame);
    void NotifyTimeChanged();
    pxr::UsdTimeCode EditTime() const;

    IconManager*        m_iconManager = nullptr;
    pxr::UsdStageRefPtr m_stage;

    // Stage range (written back to stage metadata on edit).
    double m_startFrame   = 1.0;
    double m_endFrame     = 100.0;
    double m_fps          = 24.0;

    // Playback state.
    double m_currentFrame = 1.0;
    bool   m_playing      = false;
    enum class LoopMode { None, Loop, Bounce };

    bool     m_reversed = false;           // play backward when true
    LoopMode m_loopMode = LoopMode::Loop;  // boundary behaviour

    // Auto-Key.
    bool   m_autoKey      = false;

    // Playblast state.
    bool             m_isPlayblasting     = false;
    bool             m_playblastSkipFirst = false;
    double           m_playblastFrame     = 0.0;
    int              m_playblastFrameIdx  = 0;
    bool             m_playblastWasPlaying = false;
    PlayblastSettings m_playblastSettings;
    bool             m_showPlayblastDialog = false;
};

} // namespace UsdLayerManager
