#pragma once

#include <chrono>

namespace lumacs {

/// @brief Shared cursor blinking logic for both GTK and TUI frontends.
///
/// This utility encapsulates the cursor blinking algorithm:
/// - Cursor is always visible for a threshold period after movement
/// - After the threshold, cursor blinks on/off at a fixed interval
class CursorBlinkController {
public:
    /// Default blink interval (500ms on, 500ms off)
    static constexpr std::chrono::milliseconds BLINK_INTERVAL{500};

    /// Time cursor stays visible after movement before blinking starts
    static constexpr std::chrono::milliseconds STATIONARY_THRESHOLD{1000};

    CursorBlinkController() = default;

    /// @brief Notify the controller that the cursor has moved.
    /// This resets the blink timer and makes the cursor visible.
    void notify_cursor_moved() {
        last_move_time_ = std::chrono::steady_clock::now();
        visible_ = true;
    }

    /// @brief Update the blink state based on elapsed time.
    /// @return true if the visibility state changed (requires redraw)
    bool update() {
        auto now = std::chrono::steady_clock::now();
        auto since_move = std::chrono::duration_cast<std::chrono::milliseconds>(
            now - last_move_time_);

        // Cursor stays visible during stationary threshold
        if (since_move < STATIONARY_THRESHOLD) {
            if (!visible_) {
                visible_ = true;
                return true;  // State changed
            }
            return false;
        }

        // After threshold, blink based on interval
        auto blink_phase = std::chrono::duration_cast<std::chrono::milliseconds>(
            now - last_move_time_ - STATIONARY_THRESHOLD);
        bool should_be_visible = (blink_phase.count() / BLINK_INTERVAL.count()) % 2 == 0;

        if (visible_ != should_be_visible) {
            visible_ = should_be_visible;
            return true;  // State changed
        }

        return false;
    }

    /// @brief Check if the cursor should currently be visible.
    [[nodiscard]] bool is_visible() const { return visible_; }

    /// @brief Force cursor to be visible (useful for input events).
    void force_visible() {
        visible_ = true;
        last_move_time_ = std::chrono::steady_clock::now();
    }

private:
    std::chrono::steady_clock::time_point last_move_time_ = std::chrono::steady_clock::now();
    bool visible_ = true;
};

} // namespace lumacs
