#include <Controller/InventoryController/OilRefineryController/OilRefineryController.hpp>
#include <TextFormatter/TextFormatter.hpp>
#include <Widget/Label/Label.hpp>
#include <Widget/Layout/Center/Center.hpp>
#include <Widget/Layout/Column/Column.hpp>
#include <Widget/Layout/CompoundWidget/Deck/Deck.hpp>
#include <Widget/Layout/CompoundWidget/DocColorTag/DocColorTag.hpp>
#include <Widget/Layout/CompoundWidget/DocCombustionGeneratorDiagram/DocCombustionGeneratorDiagram.hpp>
#include <Widget/Layout/CompoundWidget/DocConstructTag/DocConstructTag.hpp>
#include <Widget/Layout/CompoundWidget/DocIconTag/DocIconTag.hpp>
#include <Widget/Layout/CompoundWidget/DocItemListTag/DocItemListTag.hpp>
#include <Widget/Layout/CompoundWidget/DocItemProcDiagram/DocItemProcDiagram.hpp>
#include <Widget/Layout/CompoundWidget/DocItemProcTag/DocItemProcTag.hpp>
#include <Widget/Layout/CompoundWidget/DocItemTag/DocItemTag.hpp>
#include <Widget/Layout/CompoundWidget/DocMachineTag/DocMachineTag.hpp>
#include <Widget/Layout/CompoundWidget/DocOilRefineryDiagram/DocOilRefineryDiagram.hpp>
#include <Widget/Layout/CompoundWidget/DocPotDiagram/DocPotDiagram.hpp>
#include <Widget/Layout/CompoundWidget/DocSlotTag/DocSlotTag.hpp>
#include <Widget/Layout/CompoundWidget/DocSteamGeneratorDiagram/DocSteamGeneratorDiagram.hpp>
#include <Widget/Layout/CompoundWidget/DocView/DocView.hpp>
#include <Widget/Layout/Row/Row.hpp>
#include <Widget/Panel/Panel.hpp>

Widget* DocView::buildTag(const std::string &tagSpec)
{
    std::vector<std::string> args;
    std::stringstream ss(tagSpec);
    std::string item;

    while (std::getline(ss, item, '|'))
    {
        args.push_back(item);
    }

    if (args.size() == 0)
    {
        return new Panel();
    }

    auto handler = tagHandlers.find(args[0]);
    if (handler == tagHandlers.end())
    {
        return new Label("Unknown tag: " + args[0], Color::error);
    }

    return handler->second(args);
}

void DocView::parse(const std::string &code)
{
    std::vector<Widget*> lines;

    std::istringstream stream(code);
    std::string line;
    while (std::getline(stream, line))
    {
        lines.push_back(buildLine(line));
        lines.push_back(new Panel(glm::ivec2(0, 2)));
    }

    addChildren(new Column(lines));
}

DocView::DocView(int maxLineWidth, const std::string &code) : maxLineWidth(maxLineWidth)
{
    registerTag<DocItemTag>("item");
    registerTag<DocItemTag>("block");
    registerTag<DocMachineTag>("machine");
    registerTag<DocSlotTag>("fuelSlot", Color::fuelHighlight, "fuel slot");
    registerTag<DocSlotTag>("inputSlot", Color::inputHighlight, "input slot");
    registerTag<DocSlotTag>("equipmentSlot", Color::equipmentHighlight, "equipment slot");
    registerTag<DocSlotTag>("rechargeSlot", Color::rechargeHighlight, "recharge slot");
    registerTag<DocSlotTag>("outputSlot", Color::faded, "output slot");
    registerTag<DocSlotTag>("upgradeSlot", Color::upgradeHighlight, "upgrade slot");
    registerTag<DocSlotTag>("oilSlot", Color::oilHighlight, "oil drain slot");
    registerTag<DocSlotTag>("petrolSlot", Color::petrolHighlight, "petrol collection slot");
    registerTag<DocColorTag>("action", Color::actionEmphasis);
    registerTag<DocColorTag>("menu", Color::menuEmphasis);
    registerTag<DocItemProcTag>("itemProc");
    registerTag<DocConstructTag>("manualConstruct");
    registerTag<DocConstructTag>("constructTable");
    registerTag<DocConstructTag>("engTable");
    registerTag<DocSteamGeneratorDiagram>("steamGeneratorDiagram");
    registerTag<DocPotDiagram>("potDiagram");
    registerTag<DocIconTag>("icon");
    registerTag<DocItemListTag>("itemList");
    registerTag<DocItemProcDiagram>("itemProcDiagram");
    registerTag<DocOilRefineryDiagram>("oilRefineryDiagram");
    registerTag<DocCombustionGeneratorDiagram>("combustionGeneratorDiagram");

    parse(code);
}