#include "game/ui/menu_option.hpp"

#include <algorithm>  // Para max
#include <iterator>   // Para distance
#include <ranges>     // Para __find_fn, find

#include "core/rendering/text.hpp"  // Para Text

auto ActionListOption::getValueAsString() const -> std::string {
    if (value_getter_) {
        return value_getter_();
    }

    if (current_index_ < options_.size()) {
        return options_[current_index_];
    }

    return options_.empty() ? "" : options_[0];
}

auto ActionListOption::getMaxValueWidth(Text* text) const -> int {
    int max_width = 0;
    for (const auto& option : options_) {
        int width = text->length(option, -2);
        max_width = std::max(width, max_width);
    }
    return max_width;
}

void ActionListOption::adjustValue(bool up) {
    if (options_.empty()) {
        return;
    }

    if (up) {
        current_index_ = (current_index_ + 1) % options_.size();
    } else {
        current_index_ = (current_index_ == 0) ? options_.size() - 1 : current_index_ - 1;
    }

    // Aplicar el cambio usando el setter
    if (value_setter_ && current_index_ < options_.size()) {
        value_setter_(options_[current_index_]);
    }
}

void ActionListOption::executeAction() {
    if (action_executor_) {
        action_executor_();
    }
}

void ActionListOption::sync() {
    updateCurrentIndex();
}

void ActionListOption::updateCurrentIndex() {
    current_index_ = findCurrentIndex();
}

auto ActionListOption::findCurrentIndex() const -> size_t {
    if (!value_getter_ || options_.empty()) {
        return 0;
    }

    const std::string CURRENT_VALUE = value_getter_();
    auto it = std::ranges::find(options_, CURRENT_VALUE);

    if (it != options_.end()) {
        return static_cast<size_t>(std::distance(options_.begin(), it));
    }

    return 0;  // Valor por defecto si no se encuentra
}