// DragonX Wallet - ImGui Edition
// Copyright 2024-2026 The Hush Developers
// Released under the GPLv3

#include "console_selection_controller.h"

namespace dragonx {
namespace ui {

bool ConsoleSelectionController::isBeforeOrEqual(ConsoleTextPos a, ConsoleTextPos b)
{
    if (a.line < b.line) return true;
    if (a.line > b.line) return false;
    return a.col <= b.col;
}

void ConsoleSelectionController::beginDrag(ConsoleTextPos pos)
{
    anchor_ = pos;
    caret_  = pos;
    dragging_ = true;
    active_   = false;  // not a real selection until the caret moves off the anchor
}

void ConsoleSelectionController::updateDrag(ConsoleTextPos pos)
{
    caret_ = pos;
    // Becomes a real selection once the caret leaves the anchor; never downgrades back.
    if (caret_.line != anchor_.line || caret_.col != anchor_.col)
        active_ = true;
}

void ConsoleSelectionController::endDrag(ConsoleTextPos pos)
{
    caret_ = pos;
    dragging_ = false;
}

void ConsoleSelectionController::selectAll(int lineCount, int lastLineByteLen)
{
    if (lineCount <= 0) return;
    anchor_ = {0, 0};
    caret_  = {lineCount - 1, lastLineByteLen};
    active_ = true;
}

void ConsoleSelectionController::clear()
{
    active_   = false;
    dragging_ = false;
    anchor_ = {-1, 0};
    caret_  = {-1, 0};
}

ConsoleTextPos ConsoleSelectionController::rangeStart() const
{
    return isBeforeOrEqual(anchor_, caret_) ? anchor_ : caret_;
}

ConsoleTextPos ConsoleSelectionController::rangeEnd() const
{
    return isBeforeOrEqual(anchor_, caret_) ? caret_ : anchor_;
}

void ConsoleSelectionController::shiftForEviction(int popped)
{
    if (popped <= 0 || !active_) return;
    anchor_.line -= popped;
    caret_.line  -= popped;
    if (anchor_.line < 0 && caret_.line < 0) {
        // Entire selection was in the removed range.
        active_   = false;
        dragging_ = false;
    } else {
        if (anchor_.line < 0) { anchor_.line = 0; anchor_.col = 0; }
        if (caret_.line  < 0) { caret_.line  = 0; caret_.col  = 0; }
    }
}

std::string ConsoleSelectionController::extract(int lineCount, const ConsoleLineAccessor& getLine,
                                                const std::vector<int>& visibleIndices) const
{
    if (!active_) return "";
    return ExtractConsoleSelection(lineCount, getLine, visibleIndices,
                                   rangeStart(), rangeEnd());
}

} // namespace ui
} // namespace dragonx
