#include "trigger_dialog.h"

#include <QComboBox>
#include <QDialogButtonBox>
#include <QDoubleSpinBox>
#include <QFormLayout>
#include <QGroupBox>
#include <QHBoxLayout>
#include <QPushButton>
#include <QVBoxLayout>

TriggerDialog::TriggerDialog(
    const std::vector<std::shared_ptr<Source>>& sources,
    QWidget* parent)
    : QDialog(parent)
{
    setWindowTitle("Trigger");
    setMinimumWidth(320);

    auto* mainLay = new QVBoxLayout(this);

    // Signal selection
    auto* grpSig = new QGroupBox("Signal", this);
    auto* sigLay = new QFormLayout(grpSig);
    signalCombo_ = new QComboBox(this);
    populate(sources);
    sigLay->addRow("Signal:", signalCombo_);
    mainLay->addWidget(grpSig);

    // Edge + threshold
    auto* grpEdge = new QGroupBox("Condition", this);
    auto* edgeLay = new QFormLayout(grpEdge);
    edgeCombo_ = new QComboBox(this);
    edgeCombo_->addItems({"Rising", "Falling", "Either"});
    threshSpin_ = new QDoubleSpinBox(this);
    threshSpin_->setRange(-1e9, 1e9);
    threshSpin_->setDecimals(6);
    threshSpin_->setSingleStep(0.1);
    edgeLay->addRow("Edge:", edgeCombo_);
    edgeLay->addRow("Threshold:", threshSpin_);
    mainLay->addWidget(grpEdge);

    // Timing
    auto* grpTime = new QGroupBox("Window", this);
    auto* timeLay = new QFormLayout(grpTime);
    preSpin_ = new QDoubleSpinBox(this);
    preSpin_->setRange(0.0, 60.0);
    preSpin_->setDecimals(3);
    preSpin_->setSuffix(" s");
    preSpin_->setValue(0.01);
    postSpin_ = new QDoubleSpinBox(this);
    postSpin_->setRange(0.0, 60.0);
    postSpin_->setDecimals(3);
    postSpin_->setSuffix(" s");
    postSpin_->setValue(0.09);
    timeLay->addRow("Pre:", preSpin_);
    timeLay->addRow("Post:", postSpin_);
    mainLay->addWidget(grpTime);

    // Mode
    modeCombo_ = new QComboBox(this);
    modeCombo_->addItems({"Single", "Normal"});
    mainLay->addWidget(modeCombo_);

    // Arm/Disarm buttons
    auto* btns = new QWidget(this);
    auto* btnLay = new QHBoxLayout(btns);
    armBtn_ = new QPushButton("Arm", this);
    auto* disarmBtn = new QPushButton("Disarm", this);
    btnLay->addWidget(armBtn_);
    btnLay->addWidget(disarmBtn);
    mainLay->addWidget(btns);

    connect(armBtn_,   &QPushButton::clicked, this, &TriggerDialog::armRequested);
    connect(disarmBtn, &QPushButton::clicked, this, &TriggerDialog::disarmRequested);
}

void TriggerDialog::populate(const std::vector<std::shared_ptr<Source>>& sources)
{
    sigIds_.clear();
    signalCombo_->clear();
    for (int si = 0; si < static_cast<int>(sources.size()); ++si) {
        auto& src = sources[si];
        std::lock_guard<std::mutex> lk(src->signals_mutex);
        for (int gi = 0; gi < static_cast<int>(src->signal_states.size()); ++gi) {
            signalCombo_->addItem(
                QString("[%1] %2")
                    .arg(QString::fromStdString(src->label()))
                    .arg(QString::fromStdString(src->signal_states[gi].def.name)));
            sigIds_.push_back({si, gi});
        }
    }
}

TriggerEngine::Edge TriggerDialog::edge() const
{
    switch (edgeCombo_->currentIndex()) {
    case 0: return TriggerEngine::Edge::Rising;
    case 1: return TriggerEngine::Edge::Falling;
    default: return TriggerEngine::Edge::Either;
    }
}

TriggerEngine::Mode TriggerDialog::mode() const
{
    return modeCombo_->currentIndex() == 0
        ? TriggerEngine::Mode::Single
        : TriggerEngine::Mode::Normal;
}

double TriggerDialog::threshold() const { return threshSpin_->value(); }
double TriggerDialog::preSec()    const { return preSpin_->value();  }
double TriggerDialog::postSec()   const { return postSpin_->value(); }

std::pair<int,int> TriggerDialog::selectedSignal() const
{
    int idx = signalCombo_->currentIndex();
    if (idx < 0 || idx >= static_cast<int>(sigIds_.size()))
        return {-1, -1};
    return sigIds_[idx];
}
