#include "pch.h"

#include "legacy_brush_preset_list_services.h"

#include "canvas.h"
#include "legacy_ui_overlay_services.h"

namespace {
std::vector<NodePanelBrushPreset*> s_legacy_brush_preset_panels;
}

void NodePanelBrushPreset::execute_preset_list_plan(const pp::app::BrushPresetListPlan& plan)
{
    pp::panopainter::LegacyBrushPresetListServices services(*this);
    const auto status = pp::app::execute_brush_preset_list_plan(plan, services);
    if (!status.ok()) {
        LOG("Brush preset list action failed: %s", status.message);
    }
}

void NodePanelBrushPreset::clear_brushes()
{
    const auto plan = pp::app::plan_brush_preset_list_clear(
        static_cast<int>(m_container->m_children.size()));
    if (plan) {
        execute_preset_list_plan(plan.value());
    }
}

namespace pp::panopainter {

void register_legacy_brush_preset_panel(NodePanelBrushPreset& panel)
{
    s_legacy_brush_preset_panels.push_back(&panel);
}

void unregister_legacy_brush_preset_panel(NodePanelBrushPreset& panel)
{
    s_legacy_brush_preset_panels.erase(
        std::remove(s_legacy_brush_preset_panels.begin(), s_legacy_brush_preset_panels.end(), &panel),
        s_legacy_brush_preset_panels.end());
}

const std::vector<NodePanelBrushPreset*>& legacy_brush_preset_panels()
{
    return s_legacy_brush_preset_panels;
}

LegacyBrushPresetListServices::LegacyBrushPresetListServices(NodePanelBrushPreset& owner)
    : owner_(owner)
{
}

pp::foundation::Status LegacyBrushPresetListServices::add_current_brush_preset(int target_index)
{
    if (target_index < 0) {
        return pp::foundation::Status::out_of_range("brush preset add target is invalid");
    }
    if (!Canvas::I || !Canvas::I->m_current_brush) {
        return pp::foundation::Status::invalid_argument("current brush must be available to add a preset");
    }

    for (auto p : legacy_brush_preset_panels()) {
        p->add_brush(std::make_shared<Brush>(*Canvas::I->m_current_brush));
    }
    return pp::foundation::Status::success();
}

void LegacyBrushPresetListServices::remove_brush_preset(
    int current_index,
    int target_index,
    bool selects_target,
    bool clears_selection)
{
    for (auto p : legacy_brush_preset_panels()) {
        if (current_index < 0 || current_index >= static_cast<int>(p->m_container->m_children.size())) {
            continue;
        }

        const bool new_current = !p->m_current || p->m_container->get_child_index(p->m_current) == current_index;
        pp::panopainter::destroy_legacy_node(*p->m_container->m_children[current_index]);
        if (clears_selection) {
            p->m_current = nullptr;
        } else if (new_current && selects_target) {
            p->m_current = static_cast<NodeBrushPresetItem*>(p->m_container->m_children[target_index].get());
            p->m_current->m_selected = true;
        }
    }
}

void LegacyBrushPresetListServices::move_brush_preset(int from_index, int to_index)
{
    for (auto p : legacy_brush_preset_panels()) {
        if (from_index >= 0 && from_index < static_cast<int>(p->m_container->m_children.size())) {
            p->m_container->move_child(p->m_container->m_children[from_index].get(), to_index);
        }
    }
}

void LegacyBrushPresetListServices::select_brush_preset(int index, bool notify_brush_changed)
{
    for (auto p : legacy_brush_preset_panels()) {
        if (p->m_current) {
            p->m_current->m_selected = false;
        }
        p->m_current = static_cast<NodeBrushPresetItem*>(p->m_container->get_child_at(index));
        p->m_current->m_selected = true;
        p->m_interacted = true;
    }
    if (notify_brush_changed && owner_.on_brush_changed) {
        owner_.on_brush_changed(&owner_, owner_.m_current->m_brush);
    }
}

void LegacyBrushPresetListServices::clear_brush_presets(bool clears_selection)
{
    for (auto p : legacy_brush_preset_panels()) {
        p->m_container->remove_all_children();
        if (clears_selection) {
            p->m_current = nullptr;
        }
    }
}

void LegacyBrushPresetListServices::update_preset_empty_notification()
{
    for (auto p : legacy_brush_preset_panels()) {
        p->m_notification->SetVisibility(p->m_container->m_children.size() == 0);
    }
}

void LegacyBrushPresetListServices::save_preset_list()
{
    owner_.save();
}

} // namespace pp::panopainter
