// DragonX Wallet - ImGui Edition
// Copyright 2024-2026 The Hush Developers
// Released under the GPLv3
//
// ConsoleSelectionController — owns the console's text-selection state (anchor + caret) and
// all the pure logic around it: the mouse-drag lifecycle, select-all, ordering, extraction,
// and the index shift applied when lines are evicted from the top by the buffer cap.
//
// It is deliberately ImGui-free. Screen->text hit-testing stays in the view (it needs the
// current frame's wrapped layout + output origin); the view feeds the resulting
// ConsoleTextPos values in here. That keeps the fiddly byte-offset / eviction math unit
// testable in isolation from the renderer.

#pragma once

#include "console_text_layout.h"  // ConsoleTextPos, ConsoleLineAccessor, ExtractConsoleSelection

#include <string>
#include <vector>

namespace dragonx {
namespace ui {

class ConsoleSelectionController {
public:
    // Mouse-drag lifecycle. Positions are raw {line, col}: line = index into the full model,
    // col = byte offset within that line.
    void beginDrag(ConsoleTextPos pos);   // button press
    void updateDrag(ConsoleTextPos pos);  // movement while held
    void endDrag(ConsoleTextPos pos);     // release

    // Select the whole buffer, [0,0] .. [lineCount-1, lastLineByteLen]. No-op if empty.
    void selectAll(int lineCount, int lastLineByteLen);

    // Drop the selection entirely (also ends any in-progress drag).
    void clear();

    bool active() const { return active_; }      // a selection currently exists
    bool dragging() const { return dragging_; }  // a drag is in progress

    // Ordered bounds, start <= end. Only meaningful while active().
    ConsoleTextPos rangeStart() const;
    ConsoleTextPos rangeEnd() const;

    // After the cap evicts `popped` lines from the front, shift the selection up to track
    // the same text. Drops the selection if it fell entirely off the top.
    void shiftForEviction(int popped);

    // Selected text, or "" when inactive. `visibleIndices` are the raw line indices currently
    // shown (the selection spans raw lines but copies only the visible ones).
    std::string extract(int lineCount, const ConsoleLineAccessor& getLine,
                        const std::vector<int>& visibleIndices) const;

    // Position ordering: is a at or before b in reading order?
    static bool isBeforeOrEqual(ConsoleTextPos a, ConsoleTextPos b);

private:
    ConsoleTextPos anchor_{-1, 0};  // where the drag began / the selection origin
    ConsoleTextPos caret_{-1, 0};   // current drag position / the selection focus
    bool active_   = false;
    bool dragging_ = false;
};

} // namespace ui
} // namespace dragonx
