#include "connectandenterpage.h"
#include "ui_connectandenterpage.h"
#include "utility.h"
#include "widgets/paramdialog.h"

#include <QMessageBox>
#include <QAbstractItemView>
#include <QListView>

ConnectAndEnterPage::ConnectAndEnterPage(QWidget *parent)
    :  QWidget(parent),
      // QDialog(parent),
      ui(new Ui::ConnectAndEnterPage),
      mDieBieMS(nullptr),
      mIsConnected(false)
{
    ui->setupUi(this);

    on_pbSerialRefresh_clicked();

     ui->lbIconLogo->show();

    // hide buttons: HIDE - EXPAND - CLOSE
    //setWindowFlags(Qt::CustomizeWindowHint);
    connect(ui->cboxSerialPort, &HoverableComboBox::opened, this, &ConnectAndEnterPage::onComboBoxSerialPortOpened);
    connect(ui->cboxSerialPort, &HoverableComboBox::closed, this, &ConnectAndEnterPage::onComboBoxSerialPortClosed);

    ui->cboxSerialPort->setView(new QListView());
}

ConnectAndEnterPage::~ConnectAndEnterPage()
{
    delete ui;
}

void ConnectAndEnterPage::prepareWindowBeforeShow()
{
    ui->lbStatus->setStyleSheet("QLabel { background-color : white; color : white; }");
    ui->lbStatus->clear();

    mIsConnected = false;
    if(mDieBieMS) {
        //if(mDieBieMS->isPortConnected())
            mDieBieMS->disconnectPort();
    }

    on_pbSerialRefresh_clicked();
}



bool ConnectAndEnterPage::isConnectionPrepared()
{
//    return true;
    return mIsConnected;
}
QString ConnectAndEnterPage::portToConnect()
{
    return ui->cboxSerialPort->currentText();
}
void ConnectAndEnterPage::clearPortToConnect()
{
    ui->cboxSerialPort->clear();
}
//*
void ConnectAndEnterPage::initDieBieMS(BMSInterface* dieBieBms)
{
    // mVersion = QString::number(DT_VERSION);
    //mDieBieMS       = new BMSInterface(this);
    mDieBieMS = dieBieBms;

    mStatusInfoTime = 0;
    // mStatusLabel = new QLabel(this);
    // ui->lbStatusBar = (mStatusLabel);

    // mTimer = new QTimer(this);
    mKeyLeft    = false;
    mKeyRight   = false;
    mMcConfRead = false;

    // SEND_STATUS_INFO //
    connect(mDieBieMS, &BMSInterface::statusMessage, this, &ConnectAndEnterPage::showStatusInfo);
    connect(mDieBieMS, &BMSInterface::messageDialog, this, &ConnectAndEnterPage::showMessageDialog);
    connect(mDieBieMS, &BMSInterface::serialPortNotWritable, this, &ConnectAndEnterPage::serialPortNotWritable);
    connect(mDieBieMS->commands(), &Commands::bmsConfigCheckResult, this, &ConnectAndEnterPage::bmsConfigCheckResult);
    // connect(ui->actionAboutQt, SIGNAL(triggered(bool)),qApp, SLOT(aboutQt()));
    // connect(mTimer, SIGNAL(timeout()),this, SLOT(timerSlot()));

    // Remove the menu with the option to hide the toolbar
    // ui->mainToolBar->setContextMenuPolicy(Qt::PreventContextMenu);

    mDieBieMS->bmsConfig()->loadParamsXml("://res/config.xml");
    mDieBieMS->infoConfig()->loadParamsXml("://res/info.xml");
    // reloadPages();

    connect(mDieBieMS->bmsConfig(), SIGNAL(updated()), this, SLOT(bmsconfUpdated()));

    on_pbSerialRefresh_clicked();
}
//*/


void ConnectAndEnterPage::setDebugPrintPage(DebugPrintPage *page)
{
    mPageDebugPrint = page;
}

void ConnectAndEnterPage::showStatusInfo(QString info, bool isGood)
{
    if (isGood) {
        ui->lbStatus->setStyleSheet("QLabel { background-color : lightgreen; color : black; }");
        mPageDebugPrint->printConsole("Status: " + info + "<br>");
    } else {
        ui->lbStatus->setStyleSheet("QLabel { background-color : red; color : black; }");
        mPageDebugPrint->printConsole("<font color=\"red\">Status: " + info + "</font><br>");
    }

    mStatusInfoTime = 80;
    ui->lbStatus->setText(info);
}

bool ConnectAndEnterPage::waitProcess(QProcess &process, bool block, int timeoutMs)
{
    bool wasEnables = isEnabled();
    bool killed     = false;

    if (block) {
        setEnabled(false);
    }

    process.waitForStarted();

    QEventLoop loop;
    QTimer     timeoutTimer;
    timeoutTimer.setSingleShot(true);
    timeoutTimer.start(timeoutMs);
    connect(&process, SIGNAL(finished(int)), &loop, SLOT(quit()));
    connect(&timeoutTimer, SIGNAL(timeout()), &loop, SLOT(quit()));
    loop.exec();

    if (process.state() == QProcess::Running) {
        process.kill();
        process.waitForFinished();
        killed = true;
    }

    setEnabled(wasEnables);

    return !killed;
}

QString ConnectAndEnterPage::runCmd(QString cmd, QStringList args)
{
    QProcess process;
    process.setEnvironment(QProcess::systemEnvironment());
    process.start(cmd, args);
    waitProcess(process);
    QString res = process.readAllStandardOutput();
    process.close();
    return res;
}

void ConnectAndEnterPage::serialPortNotWritable(const QString &port)
{
    (void)port;

#ifdef Q_OS_LINUX
    QMessageBox::StandardButton reply;
    reply = QMessageBox::warning(this, tr("Connect Serial Port"),
                                 tr("The serial port is not writable. This can usually be fixed by "
                                    "adding your user to the dialout, uucp and/or lock groups. Would "
                                    "you like to do that?"),
                                 QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);

    if (reply == QMessageBox::Yes) {
        QString name = qgetenv("USER");
        if (name.isEmpty()) {
            name = qgetenv("USERNAME");
        }

        bool hasDialout = !runCmd("getent",
                                  QStringList() << "group"
                                                << "dialout")
                                   .isEmpty();
        bool hasUucp = !runCmd("getent",
                               QStringList() << "group"
                                             << "uucp")
                                .isEmpty();
        bool hasLock = !runCmd("getent",
                               QStringList() << "group"
                                             << "lock")
                                .isEmpty();

        QString grps;
        if (hasDialout) {
            grps += "dialout";
        }

        if (hasUucp) {
            if (!grps.isEmpty()) {
                grps += ",";
            }
            grps += "uucp";
        }

        if (hasLock) {
            if (!grps.isEmpty()) {
                grps += ",";
            }
            grps += "lock";
        }

        QProcess process;
        process.setEnvironment(QProcess::systemEnvironment());
        process.start("pkexec",
                      QStringList() << "usermod"
                                    << "-aG" << grps << name);
        waitProcess(process);
        if (process.exitCode() == 0) {
            showMessageDialog(tr("Command Result"),
                              tr("Result from command:\n\n"
                                 "%1\n"
                                 "You have to reboot for this "
                                 "change to take effect.")
                                      .arg(QString(process.readAllStandardOutput())),
                              true, false);
        } else {
            showMessageDialog(tr("Command Result"), tr("Running command failed."), false, false);
        }
        process.close();
    }
#endif
}

void ConnectAndEnterPage::bmsconfUpdated()
{
    mMcConfRead = true;
}

void ConnectAndEnterPage::bmsConfigCheckResult(QStringList paramsNotSet)
{
    if (!paramsNotSet.isEmpty()) {
        ParamDialog::showParams(tr("Parameters truncated"),
                                tr("The following parameters were truncated because they were set outside "
                                   "of their allowed limits."),
                                mDieBieMS->bmsConfig(), paramsNotSet, this);
    }
}

void ConnectAndEnterPage::showMessageDialog(const QString &title, const QString &msg, bool isGood, bool richText)
{
    (void)richText;

    mIsConnected = isGood;
    if (isGood) {
        QMessageBox::information(this, title, msg);
    } else {
        QMessageBox::warning(this, title, msg);
    }

    emit sigConnected();
}

BMSInterface *ConnectAndEnterPage::bms() const
{
    return mDieBieMS;
}

void ConnectAndEnterPage::setDieBieMS(BMSInterface *dieBieMS)
{
    mDieBieMS = dieBieMS;
}

void ConnectAndEnterPage::setDieBieMSEx(BMSInterface *dieBieMS)
{
    mDieBieMS = dieBieMS;

    connect(mDieBieMS->bleDevice(), SIGNAL(scanDone(QVariantMap, bool)), this, SLOT(bleScanDone(QVariantMap, bool)));

    QString lastBleAddr = QSettings().value("ble_addr").toString();
    if (lastBleAddr != "") {
        QString setName = mDieBieMS->getBleName(lastBleAddr);

        QString name;
        if (!setName.isEmpty()) {
            name += setName;
            name += " [";
            name += lastBleAddr;
            name += "]";
        } else {
            name = lastBleAddr;
        }
        // ui->bleDevBox->insertItem(0, name, lastBleAddr);
    }

    on_pbSerialRefresh_clicked();
}

void ConnectAndEnterPage::on_pbSerialRefresh_clicked()
{
    ui->pbSerialRefresh->setChecked(false);

    if (mDieBieMS) {
        ui->cboxSerialPort->clear();
        QList<VSerialInfo_t> ports = mDieBieMS->listSerialPorts();
        foreach (const VSerialInfo_t &port, ports) {
            ui->cboxSerialPort->addItem(port.name, port.systemPath);
        }
        ui->cboxSerialPort->setCurrentIndex(0);
    }
}

void ConnectAndEnterPage::on_pbConnect_clicked()
{
    // Big Connect Button on Wellcome page
    // Utility::autoconnectBlockingWithProgress(mDieBieMS, this);

    // Simple Connect Button on Connection Page
    mIsConnected = false;
    if (mDieBieMS) {
        mIsConnected = mDieBieMS->connectSerial(ui->cboxSerialPort->currentData().toString(),
                                 SERIAL_BAUD_DEFAULT_VAL // ui->spinboxSerialPort->value()
        );
    }

    if(mIsConnected)
        emit sigConnected();
    //*/
}

void ConnectAndEnterPage::on_pbExit_clicked()
{
    if(mDieBieMS)
        mDieBieMS->disconnectPort();
        //mDieBieMS->tcpInputDisconnected();

    mIsConnected = false;
    clearPortToConnect();

    emit sigReject();
    //close();
}



void ConnectAndEnterPage::onComboBoxSerialPortOpened()
{
    //ui->pbSerialRefresh->setChecked(true);
}

void ConnectAndEnterPage::onComboBoxSerialPortClosed()
{
    //ui->pbSerialRefresh->setChecked(false);
}

void ConnectAndEnterPage::on_gbWindow_clicked()
{
    int a = 0;
}

void ConnectAndEnterPage::on_gbHeader_clicked()
{
    int a = 0;
}

/*
void ConnectAndEnterPage::ShowContextMenu(const QPoint &pos)
{
   QMenu contextMenu(tr("Context menu"), this);

   QAction action1("Remove Data Point", this);
   connect(&action1, SIGNAL(triggered()), this, SLOT(removeDataPoint()));
   contextMenu.addAction(&action1);

   contextMenu.exec(mapToGlobal(pos));
}
*/
void ConnectAndEnterPage::on_pbLanguage_clicked()
{

}



