#include "ModalDialog.h"

#include <QBoxLayout>
#include <QChar>
#include <QFont>
#include <QHBoxLayout>
#include <QKeyEvent>
#include <QLabel>
#include <QPushButton>
#include <QString>

namespace
{
    // The header's own metrics, matching the row the blueprint selection dialog drew
    // before this class existed (REQ-UI-BLUEPRINT-DIALOG).
    const int  kSpacingPx         = 8;
    const int  kSmallButtonSizePx = 22;
    const QChar kCrossGlyph(0x00D7);  // U+00D7 MULTIPLICATION SIGN

    // Q dismisses an open dialog, beside the Escape that QDialog already handles
    // (REQ-UI-DIALOG-DISMISS). Ctrl must not be held, matching how the game world's
    // table separates a chord from the bare key (resolveKeyAction in
    // lib/core/ControlAction.cpp). This deliberately stays out of that table: the table
    // answers what an input does in the player's current situation, and a dialog has no
    // situation -- it holds focus and takes the key whatever the world beneath it is
    // doing.
    bool isDismissKey(const QKeyEvent& event)
    {
        return event.key() == Qt::Key_Q
               && (event.modifiers() & Qt::ControlModifier) == 0;
    }
}

ModalDialog::ModalDialog(QWidget* parent)
    : QDialog(parent)
{
    // An ordinary child widget rather than a window: the layer places it and the dim
    // behind it is the same widget's paint (REQ-UI-MODAL-CHROME). Square corners rather
    // than rounded ones -- rounding needs a translucent background, which is unreliable
    // on Windows. The border matches the build bar and the selection panel.
    setWindowFlags(Qt::Widget);
    setAttribute(Qt::WA_StyledBackground, true);
    // A type selector, so it reaches every subclass but none of the child widgets
    // inside them, which draw themselves.
    setStyleSheet(QStringLiteral(
        "ModalDialog { background-color: palette(window);"
        " border: 1px solid palette(mid); }"));
}

bool ModalDialog::isDismissible() const
{
    return false;
}

QWidget* ModalDialog::getInitialFocusWidget() const
{
    return nullptr;
}

void ModalDialog::requestDismiss()
{
    reject();
}

QHBoxLayout* ModalDialog::addHeader(QBoxLayout* mainLayout, const QString& title,
                                    bool withCloseButton)
{
    QHBoxLayout* headerLayout = new QHBoxLayout();
    headerLayout->setSpacing(kSpacingPx);

    QLabel* titleLabel = new QLabel(title, this);
    QFont headerFont = titleLabel->font();
    headerFont.setBold(true);
    titleLabel->setFont(headerFont);
    headerLayout->addWidget(titleLabel);

    // The stretch is added before the close button so a subclass inserting after the
    // title lands left of it, where the blueprint dialog's hotkey badge belongs.
    headerLayout->addStretch();

    if (withCloseButton)
    {
        QPushButton* closeButton = new QPushButton(QString(kCrossGlyph), this);
        closeButton->setFixedSize(kSmallButtonSizePx, kSmallButtonSizePx);
        connect(closeButton, &QPushButton::clicked, this, &QDialog::reject);
        headerLayout->addWidget(closeButton);
    }

    mainLayout->insertLayout(0, headerLayout);
    return headerLayout;
}

void ModalDialog::keyPressEvent(QKeyEvent* event)
{
    if (isDismissible() && isDismissKey(*event))
    {
        requestDismiss();
        return;
    }
    QDialog::keyPressEvent(event);
}
