#include "channelwidget.h"
#include <QDebug>
#include <QMessageBox>

ChannelWidget::ChannelWidget(uint16_t deviceSerial, uint16_t channelNumber,
                             std::shared_ptr<struct eismultiplexer> multiplexer,
                             QWidget *parent)
        :
        QWidget(parent),
        deviceSerial(deviceSerial),
        channelNumber(channelNumber),
        multiplexer(multiplexer),
        checkbox("Enable"),
        devicelabel(QString::asprintf("Device %04u", deviceSerial)),
        channellabel(QString::asprintf("Channel %u", channelNumber)),
        ganglabel("Ganged:")
{
        hlayout.addLayout(&labellayout);
        vlayout.addLayout(&hlayout);

        labellayout.addWidget(&devicelabel);
        labellayout.addWidget(&channellabel);

        line.setGeometry(QRect(320, 150, 118, 3));
        line.setFrameShape(QFrame::HLine);
        line.setFrameShadow(QFrame::Sunken);
        vlayout.addWidget(&line);

        gangcombo.addItem("Unganged");

        hlayout.addStretch();
        hlayout.addWidget(&ganglabel);
        hlayout.addWidget(&gangcombo);
        hlayout.addWidget(&checkbox);

        connect(&checkbox, &QCheckBox::toggled, this, &ChannelWidget::onChannelToggled);
        connect(&gangcombo, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ChannelWidget::onGangComboChanged);

        setFixedHeight(96);
        setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);

        setLayout(&vlayout);
}

ChannelWidget::~ChannelWidget()
{

}

uint16_t ChannelWidget::getDeviceSerial() const
{
        return deviceSerial;
}

uint16_t ChannelWidget::getChannelNumber() const
{
        return channelNumber;
}

bool ChannelWidget::isChecked() const
{
        return checkbox.isChecked();
}

void ChannelWidget::onChannelToggled(bool checked)
{
        if (checked)
        {
                // Emit signal before actually turning on the channel
                emit channelAboutToBeTurnedOn(deviceSerial, channelNumber);
        }

        channel_t channelFlag = static_cast<channel_t>(1 << channelNumber);
        if (checked)
        {
                if (eismultiplexer_connect_channel(multiplexer.get(), channelFlag) < 0)
                {
                        QMessageBox::warning(this, tr("Connection Failed"),
                                             tr("Failed to connect channel %1 on device %2").arg(channelNumber).arg(deviceSerial));
                        qWarning() << "Failed to connect channel" << channelNumber << "on device" << deviceSerial;
                        checkbox.blockSignals(true);
                        checkbox.setChecked(false);
                        setEnabled(false);
                }
        }
        else
        {
                if (eismultiplexer_disconnect_channel(multiplexer.get(), channelFlag) < 0)
                {
                        QMessageBox::warning(this, tr("Disconnection Failed"),
                                             tr("Failed to disconnect channel %1 on device %2").arg(channelNumber).arg(deviceSerial));
                        qWarning() << "Failed to disconnect channel" << channelNumber << "on device" << deviceSerial;
                        checkbox.blockSignals(true);
                        checkbox.setChecked(true);
                        setEnabled(false);
                }
        }

        // Emit state change signal for other channels that might be ganged to this one
        emit channelStateChanged(deviceSerial, channelNumber, checked);
}

void ChannelWidget::onGangComboChanged(int index)
{
        if (index == 0) {
            // Unganged selected - reset ganged channel tracking
            gangedDeviceSerial = -1;
            gangedChannelNumber = -1;
            checkbox.setEnabled(true);
            checkbox.setChecked(false);
            checkbox.setChecked(false);
        } else {
            // A ganged channel was selected
            QString currentText = gangcombo.currentText();
            QStringList parts = currentText.split(", ");
            if (parts.size() == 2) {
                bool ok1, ok2;
                uint16_t gangedSerial = parts[0].toUInt(&ok1);
                uint16_t gangedChannel = parts[1].toUInt(&ok2);

                if (ok1 && ok2) {
                    setGangedChannel(gangedSerial, gangedChannel);
                }
            }
        }
}

void ChannelWidget::onOtherChannelStateChanged(uint16_t deviceSerial, uint16_t channelNumber, bool checked)
{
        // If this channel is ganged to the channel that changed state
        if (gangedDeviceSerial == deviceSerial && gangedChannelNumber == channelNumber) {
            // Update our checkbox state to follow the ganged channel
            checkbox.blockSignals(true);
            checkbox.setChecked(checked);
            checkbox.blockSignals(false);
        }
}

void ChannelWidget::updateGangCombo()
{
        // Clear existing items except "Unganged"
        while (gangcombo.count() > 1) {
            gangcombo.removeItem(1);
        }
}

void ChannelWidget::updateCheckboxState()
{
        if (gangedDeviceSerial >= 0 && gangedChannelNumber >= 0) {
            checkbox.setEnabled(false);
            // TODO check current ganged channel state
        } else {
            checkbox.setEnabled(true);
        }
}

void ChannelWidget::setGangedChannel(uint16_t gangedDeviceSerial, uint16_t gangedChannelNumber)
{
        this->gangedDeviceSerial = gangedDeviceSerial;
        this->gangedChannelNumber = gangedChannelNumber;

        // Update checkbox state to follow the ganged channel
        updateCheckboxState();
}

