#pragma once

#include <string>
#include <deque>
#include <optional>

#include "lumacs/buffer.hpp" // For Position and Range

namespace lumacs {

/// @brief Implements an Emacs-like kill ring (clipboard history).
/// The kill ring stores killed (cut) text in a circular buffer.
/// Also tracks yank position state for yank-pop functionality.
class KillRingManager {
public:
    explicit KillRingManager(size_t max_size = 60);

    /// @brief Pushes text onto the kill ring. If the last entry was also a kill
    /// (not a yank), it appends to that entry. Otherwise, it creates a new entry.
    /// @param text The text to push.
    void push(const std::string& text);

    /// @brief Retrieves the current (most recently pushed) entry in the kill ring.
    /// @return The current entry. Returns empty string if ring is empty.
    [[nodiscard]] std::string current() const;

    /// @brief Rotates the kill ring and retrieves the previous entry.
    /// Used for `yank-pop`.
    /// @return The previous entry. Returns empty string if ring is empty.
    [[nodiscard]] std::string previous();

    /// @brief Checks if the kill ring is empty.
    [[nodiscard]] bool empty() const { return ring_.empty(); }

    /// @brief Clears the kill ring.
    void clear() { ring_.clear(); }

    // === Yank State Tracking ===

    /// @brief Record the start and end positions of a yank operation.
    /// @param start The position where the yank started.
    /// @param end The position where the yank ended.
    void set_yank_range(Position start, Position end);

    /// @brief Get the yank start position if a yank was performed.
    [[nodiscard]] std::optional<Position> yank_start() const { return last_yank_start_; }

    /// @brief Get the yank end position if a yank was performed.
    [[nodiscard]] std::optional<Position> yank_end() const { return last_yank_end_; }

    /// @brief Update just the yank end position (after yank-pop replaces text).
    void set_yank_end(Position end) { last_yank_end_ = end; }

    /// @brief Check if a yank operation has been recorded.
    [[nodiscard]] bool has_yank_state() const {
        return last_yank_start_.has_value() && last_yank_end_.has_value();
    }

    /// @brief Clear the yank state (e.g., after a non-yank command).
    void clear_yank_state() {
        last_yank_start_.reset();
        last_yank_end_.reset();
    }

private:
    std::deque<std::string> ring_;
    size_t max_size_;
    bool last_action_was_kill_ = false; // Tracks if the last push was a kill or append

    // Yank position tracking (moved from EditorCore)
    std::optional<Position> last_yank_start_;
    std::optional<Position> last_yank_end_;
};

} // namespace lumacs
