#include <BlockRegistry/BlockRegistry.hpp>
#include <ItemStack/ItemStack.hpp>
#include <Widget/IconLabel/IconLabel.hpp>
#include <Widget/Label/Label.hpp>
#include <Widget/Layout/CompoundWidget/DocConstructTag/DocConstructTag.hpp>
#include <Widget/Layout/CompoundWidget/Form/Form.hpp>
#include <Widget/Layout/CompoundWidget/IconText/IconText.hpp>
#include <Widget/Layout/Frame/Frame.hpp>
#include <Widget/Panel/Panel.hpp>
#include <Widget/StaticItemSlot/StaticItemSlot.hpp>
#include <string>
#include <unordered_map>

const DocConstructTag::LevelSpec& DocConstructTag::getLevelSpec(const std::string &tag)
{
    static const std::unordered_map<std::string, LevelSpec> levelSpecs = {
        {"manualConstruct", {Material::kevinAvatar, "Manual Construction"}},
        {"constructTable", {blockRegistry.getBlockByName("main:constructTable").iconMaterial, "Construction Table"}},
        {"engTable", {blockRegistry.getBlockByName("main:engineeringTable").iconMaterial, "Engineering Table"}}
    };

    return levelSpecs.at(tag);
}

DocConstructTag::DocConstructTag(const std::vector<std::string> &args)
{
    if ((args.size() % 2) != 1 || args.size() < 5)
    {
        addChildren(new Label("<!!!>", Color::error));
        return;
    }

    const auto &levelSpec = getLevelSpec(args[0]);

    outputStack = *ItemStack::fromItemOrBlockName(args[1], std::stoi(args[2]));

    std::vector<Widget*> inputs;
    for (size_t i = 3; i < args.size(); i += 2)
    {
        size_t stackIndex = inputStacks.size();
    
        inputStacks.push_back(*ItemStack::fromItemOrBlockName(args[i], std::stoi(args[i + 1])));
        inputs.push_back(new StaticItemSlot([this, stackIndex]() { return inputStacks[stackIndex]; }));
    }

    addChildren(
        new Frame(
            new Form(
                new IconText(levelSpec.icon, levelSpec.label),
                new Column(
                    new Panel(glm::ivec2(120, 0)),
                    new Center(
                        new Deck<Row, Center>(
                            new Row(inputs),
                            new IconLabel(Material::rightArrow),
                            new StaticItemSlot([this]() { return outputStack; })
                        )
                    )
                )
            )
        )
    );
}