#include "ItemTooltip.h"

#include <QFont>
#include <QLabel>
#include <QVBoxLayout>

#include "DisplayName.h"
#include "GameConfig.h"
#include "ItemProducers.h"
#include "RecipeLineRow.h"
#include "RecipesConfig.h"
#include "Simulation.h"

namespace
{

std::vector<RecipeLineRow::Amount> toAmounts(
    const std::vector<RecipeIngredient>& ingredients)
{
    std::vector<RecipeLineRow::Amount> amounts;
    amounts.reserve(ingredients.size());
    for (const RecipeIngredient& ingredient : ingredients)
    {
        amounts.push_back(RecipeLineRow::Amount{ ingredient.item, ingredient.amount });
    }
    return amounts;
}

}  // namespace


void ItemTooltip::attachTo(QWidget& target, const ItemTooltipContext& context,
                           const std::string& itemId, TooltipTrigger::Trigger trigger)
{
    ItemTooltip* tooltip = new ItemTooltip(context, itemId, &target);
    TooltipTrigger::attach(target, *tooltip, trigger);
}

ItemTooltip::ItemTooltip(const ItemTooltipContext& context, const std::string& itemId,
                         QWidget* parent)
    : Tooltip(parent)
    , m_context(context)
    , m_itemId(itemId)
{
}

void ItemTooltip::refreshContent()
{
    clearContent();
    QVBoxLayout* layout = getContentLayout();

    // The heading names the item. For an input chip this is the only place it is named
    // at all, since such a chip carries a count and no name (REQ-UI-SINGLE-SELECTION).
    QLabel* heading =
        new QLabel(QString::fromStdString(toDisplayName(m_itemId)), this);
    QFont headingFont = heading->font();
    headingFont.setBold(true);
    heading->setFont(headingFont);
    layout->addWidget(heading);
    heading->show();

    const ItemProduction production =
        findItemProduction(m_itemId, *m_context.sim, *m_context.config);

    // Scrap is salvaged from debris rather than crafted (REQ-RES-DEBRIS-DROP), so it
    // says where it comes from in place of the caption and lists nothing.
    QLabel* caption = new QLabel(production.origin == ItemOrigin::Salvaged
        ? tr("Salvaged from debris")
        : tr("Produced by"), this);
    layout->addWidget(caption);
    caption->show();

    if (production.origin == ItemOrigin::Undiscovered)
    {
        // Made somehow, but by nothing the player has unlocked -- named without being
        // shown a path they cannot take yet (REQ-UI-ITEM-TOOLTIP).
        QLabel* undiscovered = new QLabel(tr("Undiscovered"), this);
        layout->addWidget(undiscovered);
        undiscovered->show();
        return;
    }

    for (const RecipeDef* recipe : production.recipes)
    {
        RecipeLineRow::Spec spec;
        spec.building        = recipe->building;
        spec.name            = QString::fromStdString(toDisplayName(recipe->id));
        spec.inputs          = toAmounts(recipe->inputs);
        // The paths this producer can currently take (REQ-LOCK-OUTPUT-POOL). One of them
        // yields the item being explained -- findItemProduction listed the recipe only
        // because one does -- so the line never comes back empty here.
        spec.outputGroups    = RecipeLineRow::toUnlockedOutputGroups(
            *recipe,
            [this](const std::string& id) { return m_context.sim->isItemUnlocked(id); });
        spec.durationSeconds = recipe->durationSeconds;

        // Boxed, because an item with several producers stacks several of these and a run
        // of bare lines reads as one field of icons (REQ-UI-ITEM-TOOLTIP). The items it
        // names carry no tooltip of their own: this is already one
        // (REQ-UI-ITEM-VALUE-TOOLTIP).
        RecipeLineRow* line =
            new RecipeLineRow(m_context.itemIcons, m_context.buildingIcons, this);
        line->setCardChrome(true);
        layout->addWidget(line);
        line->setLine(spec);
    }
}
