
#include <Color/Color.hpp>
#include <ItemFilter/ItemFilterByName/ItemFilterByName.hpp>
#include <ItemRegistry/ItemRegistry.hpp>
#include <ItemStack/ItemStack.hpp>
#include <Material/Material.hpp>
#include <Widget/IconLabel/IconLabel.hpp>
#include <Widget/Label/Label.hpp>
#include <Widget/Layout/Center/Center.hpp>
#include <Widget/Layout/CompoundWidget/Deck/Deck.hpp>
#include <Widget/Layout/CompoundWidget/Explorer/Explorer.hpp>
#include <Widget/Layout/CompoundWidget/ItemProcRuleExplorer/ItemProcRuleExplorer.hpp>
#include <Widget/Layout/Row/Row.hpp>
#include <Widget/Panel/Panel.hpp>
#include <Widget/StaticItemSlot/StaticItemSlot.hpp>

void ItemProcRuleExplorer::buildRuleCache(MapCallback getOutputStack)
{
    std::vector<ItemStack> allStacks;
    itemRegistry.getAllStacks(allStacks);

    for (ItemStack &stack : allStacks)
    {
        ItemStack output = getOutputStack(stack);
        if (output.isEmpty())
        {
            continue;
        }

        rules.push_back({stack, output});
    }
}

ItemProcRuleExplorer::ItemProcRuleExplorer(std::string stateUrl, MapCallback getOutputStack)
{
    buildRuleCache(getOutputStack);

    addChildren(
        new Explorer<Rule>(
            stateUrl,
            [this](std::string query)
            {
                std::vector<Rule> results;
                ItemFilterByName filter(query);

                for (Rule &rule : rules)
                {
                    if (filter.matches(rule.input) || filter.matches(rule.output))
                    {
                        results.push_back(rule);
                    }
                }

                return results;
            },

            [](Rule rule) -> Widget*
            {
                return new Center(
                    new Deck<Row, Center>(
                        new StaticItemSlot(
                            [rule]()
                            {
                                return rule.input;
                            }
                        ),
                        new IconLabel(Material::rightArrow),
                        new Panel(glm::ivec2(2, 0)),
                        new StaticItemSlot(
                            [rule]()
                            {
                                return rule.output;
                            }
                        )
                    )
                );
            }
        )
    );
}