#include "CrateSyncCtlDialog.h"
#include "ui_CrateSyncCtlDialog.h"
#include "LtrdConnection.h"
#include <QMessageBox>


CrateSyncCtlDialog::CrateSyncCtlDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::CrateSyncCtlDialog),
    m_crate_open(false) {

    ui->setupUi(this);

    connect(ui->btnOutsSetup, SIGNAL(clicked()), SLOT(setSyncOuts()));
    connect(ui->btnStartSetMode, SIGNAL(clicked()), SLOT(startMarkSetMode()));
    connect(ui->btnStartProgGen, SIGNAL(clicked()), SLOT(startMarkGen()));
    connect(ui->btnSecondStart, SIGNAL(clicked()), SLOT(startSecondMarks()));
    connect(ui->btnSecondStop, SIGNAL(clicked()), SLOT(stopSecondMarks()));
    connect(ui->chkOutEn, SIGNAL(stateChanged(int)), SLOT(updateDoutEnState()));

    setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowSystemMenuHint  | Qt::WindowTitleHint | Qt::WindowCloseButtonHint);

}

int CrateSyncCtlDialog::setCrate(LtrCrateInfo *crate) {
    if (m_crate_open) {
        LTR_Close(&hcrate);
    }

    LTR_Init(&hcrate);
    INT err = crate->openConnection(&hcrate);
    if (err == LTR_OK) {
        m_crate_open = true;
        crate_name = crate->infoString();
        fillUi();

        setDoutBox(ui->cbDout1, LTR_DIGOUT_START);
        setDoutBox(ui->cbDout2, LTR_DIGOUT_SECOND);
        updateDoutEnState();
    }
    return err;
}

CrateSyncCtlDialog::~CrateSyncCtlDialog() {
    if (m_crate_open) {
        LTR_Close(&hcrate);
    }
    delete ui;
}

void CrateSyncCtlDialog::changeEvent(QEvent *e) {
    QDialog::changeEvent(e);
    switch (e->type()) {
        case QEvent::LanguageChange:
            ui->retranslateUi(this);
            fillUi();
            break;
        default:
            break;
    }
}

void CrateSyncCtlDialog::setSyncOuts() {
    TLTR_CONFIG cfg;
    for (int i = 0; i < sizeof(cfg.userio)/sizeof(cfg.userio[0]); i++) {
        cfg.userio[i] = LTR_USERIO_DEFAULT;
    }

    cfg.digout[0] = ui->cbDout1->itemData(ui->cbDout1->currentIndex()).toInt();
    cfg.digout[1] = ui->cbDout2->itemData(ui->cbDout2->currentIndex()).toInt();
    cfg.digout_en = ui->chkOutEn->isChecked();

    INT err = LTR_Config(&hcrate, &cfg);
    if (err != LTR_OK) {
        QMessageBox::critical(this, tr("Error"),
                              tr("Cannot configure crate SYNC outputs") + ": " +
                              LtrdConnection::getErrorString(err));
    }
}

void CrateSyncCtlDialog::startMarkSetMode() {
    INT mode = ui->cbStartMode->itemData(ui->cbStartMode->currentIndex()).toInt();
    INT err = LTR_MakeStartMark(&hcrate, mode);
    if (err != LTR_OK) {
        QMessageBox::critical(this, tr("Error"),
                              tr("Cannot set START mark generation mode") + ": " +
                              LtrdConnection::getErrorString(err));
    }
}

void CrateSyncCtlDialog::startMarkGen() {
    INT err = LTR_MakeStartMark(&hcrate, LTR_MARK_INTERNAL);
    if (err != LTR_OK) {
        QMessageBox::critical(this, tr("Error"),
                              tr("Cannot generate START mark") + ": " +
                              LtrdConnection::getErrorString(err));
    }
}

void CrateSyncCtlDialog::startSecondMarks() {
    INT mode = ui->cbSecondMode->itemData(ui->cbSecondMode->currentIndex()).toInt();
    INT err = LTR_StartSecondMark(&hcrate, mode);
    if (err != LTR_OK) {
        QMessageBox::critical(this, tr("Error"),
                              tr("Cannot start SECOND marks generation") + ": " +
                              LtrdConnection::getErrorString(err));
    }
}

void CrateSyncCtlDialog::stopSecondMarks() {
    INT err = LTR_StopSecondMark(&hcrate);
    if (err != LTR_OK) {
        QMessageBox::critical(this, tr("Error"),
                              tr("Cannot stop SECOND marks generation") + ": " +
                              LtrdConnection::getErrorString(err));
    }
}

void CrateSyncCtlDialog::updateDoutEnState() {
    bool en = ui->chkOutEn->isChecked();
    ui->cbDout1->setEnabled(en);
    ui->cbDout2->setEnabled(en);
}

void CrateSyncCtlDialog::updateTitle() {
    setWindowTitle(tr("%1 synchronization control").arg(crate_name));
}

void CrateSyncCtlDialog::fillUi() {
    fillDoutBox(ui->cbDout1);
    fillDoutBox(ui->cbDout2);
    fillStartModeBox(ui->cbStartMode);
    fillSecondModeBox(ui->cbSecondMode);
    updateTitle();
}

void CrateSyncCtlDialog::fillDoutBox(QComboBox *box) {
    int idx = 0;
    if (box->count() != 0) {
        idx = box->currentIndex();
        box->clear();
    }

    box->addItem(tr("Constant low level (logical 0)"), LTR_DIGOUT_CONST0);
    box->addItem(tr("Constant high level (logical 1)"), LTR_DIGOUT_CONST1);
    box->addItem(tr("Translate DIGIN1 signal state"), LTR_DIGOUT_DIGIN1);
    box->addItem(tr("Translate DIGIN2 signal state"), LTR_DIGOUT_DIGIN2);
    box->addItem(tr("Translate START mark"), LTR_DIGOUT_START);
    box->addItem(tr("Translate SECOND mark"), LTR_DIGOUT_SECOND);
    box->setCurrentIndex(idx);
}

void CrateSyncCtlDialog::fillStartModeBox(QComboBox *box) {
    int idx = 0;
    if (box->count() != 0) {
        idx = box->currentIndex();
        box->clear();
    }
    box->addItem(tr("Off"), LTR_MARK_OFF);
    fillExtDiginMarkModes(box);
    box->setCurrentIndex(idx);
}

void CrateSyncCtlDialog::fillSecondModeBox(QComboBox *box) {
    int idx = 0;
    if (box->count() != 0) {
        idx = box->currentIndex();
        box->clear();
    }
    box->addItem(tr("Internal crate timer"), LTR_MARK_INTERNAL);
    fillExtDiginMarkModes(box);
    box->setCurrentIndex(idx);
}

void CrateSyncCtlDialog::fillExtDiginMarkModes(QComboBox *box) {
    box->addItem(tr("On DIGIN1 input signal rise"), LTR_MARK_EXT_DIGIN1_RISE);
    box->addItem(tr("On DIGIN1 input signal fall"), LTR_MARK_EXT_DIGIN1_FALL);
    box->addItem(tr("On DIGIN2 input signal rise"), LTR_MARK_EXT_DIGIN2_RISE);
    box->addItem(tr("On DIGIN2 input signal fall"), LTR_MARK_EXT_DIGIN2_FALL);
}

void CrateSyncCtlDialog::setDoutBox(QComboBox *box, en_LTR_DigOutCfg outcfg) {
    for (int i = 0; i < box->count(); i++) {
        if (box->itemData(i).toInt() == outcfg) {
            box->setCurrentIndex(i);
            break;
        }
    }
}
