#include "BeltItemList.h"

#include <map>
#include <string>

#include <QPoint>
#include <QVBoxLayout>

#include "BeltSystem.h"
#include "DisplayName.h"
#include "EmptyNote.h"
#include "FactoryQueries.h"
#include "ItemChipRow.h"
#include "ItemType.h"
#include "SectionBox.h"
#include "Simulation.h"

BeltItemList::BeltItemList(const SelectionContext& context,
                           const std::vector<BuildingId>& ids, QWidget* parent)
    : QWidget(parent)
    , m_context(context)
    , m_ids(ids)
{
    QVBoxLayout* layout = new QVBoxLayout(this);
    layout->setContentsMargins(0, 0, 0, 0);
    layout->setSpacing(0);

    m_section   = new SectionBox(tr("Items"), this);
    m_chips     = new ItemChipRow(m_context, m_section);
    m_emptyNote = new EmptyNote(tr("No items"), m_section);
    m_section->getContentLayout()->addWidget(m_chips);
    m_section->getContentLayout()->addWidget(m_emptyNote);
    layout->addWidget(m_section);

    refresh();
}

void BeltItemList::refresh()
{
    // Both the list and the clear action derive their tiles the same way, so what is
    // listed is what the button removes (REQ-UI-BELT-ITEMS, REQ-UI-BELT-CLEAR).
    const std::vector<QPoint> tiles =
        collectBeltTiles(m_context.sim->getFactoryState(), m_ids);
    const std::map<ItemType, int> counts = m_context.sim->getBelts().countItems(tiles);

    // Keyed by item type, so the chips come out ordered by item id and a chip does not
    // move as its count changes (REQ-UI-BELT-ITEMS).
    std::vector<ItemChipRow::Entry> entries;
    entries.reserve(counts.size());
    for (const std::pair<const ItemType, int>& count : counts)
    {
        ItemChipRow::Entry entry;
        entry.itemId    = count.first.id;
        entry.countText = QString::number(count.second);
        entry.subLine   = QString::fromStdString(toDisplayName(count.first.id));
        entries.push_back(entry);
    }

    // A belt has no fixed set of item types it can hold, unlike a building's buffers, so
    // there is no chip to show as `0` and the note takes the section's place instead.
    m_chips->setEntries(entries);
    m_emptyNote->setVisible(entries.empty());
}
