#include "trigger_toolbar.h"

#include <QComboBox>
#include <QDoubleSpinBox>
#include <QFormLayout>
#include <QGroupBox>
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>
#include <QWidget>

TriggerToolBar::TriggerToolBar(QWidget* parent)
    : QDockWidget("Trigger", parent)
{
    setAllowedAreas(Qt::BottomDockWidgetArea | Qt::TopDockWidgetArea);
    setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable |
                QDockWidget::DockWidgetClosable);

    auto* container = new QWidget(this);
    auto* mainLay   = new QHBoxLayout(container);
    mainLay->setContentsMargins(6, 4, 6, 4);
    mainLay->setSpacing(12);

    // ── Signal & condition ────────────────────────────────────────────
    auto* grpSig = new QGroupBox("Signal", container);
    auto* sigLay = new QFormLayout(grpSig);
    sigLay->setSpacing(4);
    signalCombo_ = new QComboBox(grpSig);
    signalCombo_->setMinimumWidth(180);
    sigLay->addRow("Signal:", signalCombo_);
    mainLay->addWidget(grpSig);

    auto* grpCond = new QGroupBox("Condition", container);
    auto* condLay = new QFormLayout(grpCond);
    condLay->setSpacing(4);
    edgeCombo_ = new QComboBox(grpCond);
    edgeCombo_->addItems({"Rising", "Falling", "Either"});
    threshSpin_ = new QDoubleSpinBox(grpCond);
    threshSpin_->setRange(-1e9, 1e9);
    threshSpin_->setDecimals(4);
    threshSpin_->setSingleStep(0.1);
    threshSpin_->setMinimumWidth(100);
    condLay->addRow("Edge:", edgeCombo_);
    condLay->addRow("Threshold:", threshSpin_);
    mainLay->addWidget(grpCond);

    // ── Timing ────────────────────────────────────────────────────────
    auto* grpTime = new QGroupBox("Window", container);
    auto* timeLay = new QFormLayout(grpTime);
    timeLay->setSpacing(4);
    preSpin_ = new QDoubleSpinBox(grpTime);
    preSpin_->setRange(0.0, 60.0);
    preSpin_->setDecimals(3);
    preSpin_->setSuffix(" s");
    preSpin_->setValue(0.01);
    postSpin_ = new QDoubleSpinBox(grpTime);
    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 ──────────────────────────────────────────────────────────
    auto* grpMode = new QGroupBox("Mode", container);
    auto* modeLay = new QFormLayout(grpMode);
    modeLay->setSpacing(4);
    modeCombo_ = new QComboBox(grpMode);
    modeCombo_->addItems({"Single", "Normal"});
    modeLay->addRow("Mode:", modeCombo_);
    mainLay->addWidget(grpMode);

    // ── Arm/Disarm + status ───────────────────────────────────────────
    auto* ctrlWidget = new QWidget(container);
    auto* ctrlLay    = new QVBoxLayout(ctrlWidget);
    ctrlLay->setSpacing(4);
    armBtn_     = new QPushButton("Arm",    ctrlWidget);
    disarmBtn_  = new QPushButton("Disarm", ctrlWidget);
    statusLabel_= new QLabel("Idle",        ctrlWidget);
    statusLabel_->setAlignment(Qt::AlignCenter);
    ctrlLay->addWidget(armBtn_);
    ctrlLay->addWidget(disarmBtn_);
    ctrlLay->addWidget(statusLabel_);
    mainLay->addWidget(ctrlWidget);

    mainLay->addStretch();
    setWidget(container);

    connect(armBtn_,    &QPushButton::clicked, this, &TriggerToolBar::armRequested);
    connect(disarmBtn_, &QPushButton::clicked, this, &TriggerToolBar::disarmRequested);
}

void TriggerToolBar::refreshSources(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});
        }
    }
}

void TriggerToolBar::setStatus(const QString& text)
{
    statusLabel_->setText(text);
}

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

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

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

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