#include "ExpandButton.h"

#include <QLabel>
#include <QPalette>
#include <QPixmap>
#include <QVBoxLayout>

#include "Command.h"
#include "CommandRequestedEvent.h"
#include "EventManager.h"
#include "FloatingLayoutInvalidatedEvent.h"
#include "IconCaption.h"
#include "ItemIconCache.h"
#include "ItemTooltip.h"
#include "Simulation.h"
#include "TooltipTrigger.h"

ExpandButton::ExpandButton(const ItemTooltipContext& context, QWidget* parent)
    : OptionButton(parent)
    , m_context(context)
{
    QVBoxLayout* face = new QVBoxLayout(this);
    face->setContentsMargins(8, 4, 8, 4);
    face->setSpacing(1);

    // Names the action, not an item, so it says nothing of its own and stays out of the
    // mouse's way -- a click anywhere on the face reaches the button beneath it.
    QLabel* actionLabel = new QLabel(tr("Expand"), this);
    actionLabel->setAlignment(Qt::AlignCenter);
    actionLabel->setAttribute(Qt::WA_TransparentForMouseEvents, true);
    face->addWidget(actionLabel);

    // The cost line, deliberately not transparent to the mouse: it names an item and has
    // to be hoverable to explain it. Hover only, the click being the button's
    // (REQ-UI-ITEM-VALUE-TOOLTIP). A label ignores presses, so they still reach the
    // button.
    m_costLabel = new QLabel(this);
    m_costLabel->setAlignment(Qt::AlignCenter);
    face->addWidget(m_costLabel);
    ItemTooltip::attachTo(*m_costLabel, m_context, kBlockItemId,
                          TooltipTrigger::Trigger::HoverOnly);

    // Carries no payload: the simulation derives the cost and the column count from its
    // own expansion counter (REQ-EXP-UNLOCK, REQ-GW-ASTEROID-EXPAND).
    connect(this, &QPushButton::clicked, this, []() {
        EventManager::getInstance()->sendEventImmediately(
            std::make_shared<CommandRequestedEvent>(
                std::make_shared<ExpandAsteroidCommand>()));
    });

    refresh();
    registerForEvents();
}

ExpandButton::~ExpandButton()
{
    unregisterForEvents();
}

void ExpandButton::handleEvent(std::shared_ptr<const ExpansionCostChangedEvent> /*event*/)
{
    refresh();
}

void ExpandButton::handleEvent(std::shared_ptr<const BuildingBlocksChangedEvent> /*event*/)
{
    refresh();
}

void ExpandButton::refresh()
{
    const int blocks        = m_context.sim->getBuildingBlocksStock();
    const int expansionCost = m_context.sim->getCurrentExpansionCost();

    setEnabled(blocks >= expansionCost);

    // The cost reads as it does everywhere else: the number, then the block icon in place
    // of a trailing `Blocks` word (REQ-UI-BLOCKS-ICON, REQ-UI-ITEM-ICON). With no icon
    // file the word comes back, since nothing else on the line would name the item.
    const QPixmap icon = m_context.itemIcons->getInlineIcon(kBlockItemId, font());
    if (icon.isNull())
    {
        m_costLabel->setPixmap(QPixmap());
        m_costLabel->setText(tr("%1 Blocks").arg(expansionCost));
    }
    else
    {
        m_costLabel->setText(QString());
        m_costLabel->setPixmap(renderCaptionWithIcon(
            QString::number(expansionCost), icon, font(),
            palette().color(isEnabled() ? QPalette::Active : QPalette::Disabled,
                            QPalette::ButtonText)));
    }

    // A cost of a different width re-centers the button on its columns, which is the
    // owner's to do (ui/FloatingPanel.h, MainWindow::placeExpandButton).
    EventManager::getInstance()->sendEventImmediately(
        std::make_shared<FloatingLayoutInvalidatedEvent>());
}
