/*****************************************************************************
 *
 * Testmanager - Graphical Automation and Visualisation Tool
 *
 * Copyright (C) 2018-2019  Florian Pose <fp@igh.de>
 *
 * This file is part of Testmanager.
 *
 * Testmanager is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option)
 * any later version.
 *
 * Testmanager is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with Testmanager. If not, see <http://www.gnu.org/licenses/>.
 *
 ****************************************************************************/

#include "ReplaceDialog.h"

#include "DataSource.h"
#include "LoginDialog.h"

#include <QMessageBox>
#include <QLineEdit>
#include <QSettings>
#include <QtPdCom1/LoginManager.h>

/****************************************************************************/

ReplaceDialog::ReplaceDialog(DataModel *dataModel, DataSource *dataSource,
        QWidget *parent):
    QDialog(parent),
    dataModel(dataModel),
    dataSource(dataSource),
    newDataSource(nullptr)
{
    setupUi(this);

    QString url(dataSource->getUrl().toString());
    labelAddress->setText(tr("New URL for datasource %1:").arg(url));

    QSettings settings;
    recentSources = settings.value("recentSources").toStringList();

    if (recentSources.size()) {
        foreach (QString source, recentSources) {
            addressComboBox->addItem(source);
        }
    }
    else {
        QString defaultUrl("msr://localhost");
#if QT_VERSION < 0x050000
        addressComboBox->lineEdit()->setText(defaultUrl);
#else
        addressComboBox->setCurrentText(defaultUrl);
#endif
    }
}

/****************************************************************************/

ReplaceDialog::~ReplaceDialog()
{
    if (newDataSource) {
        newDataSource->disconnectFromHost();
        delete newDataSource;
    }
}

/****************************************************************************/

DataSource *ReplaceDialog::adoptSource()
{
    DataSource *ret = newDataSource;
    newDataSource = nullptr; // forget about it
    return ret;
}

/****************************************************************************/

ReplaceDialog::Mode ReplaceDialog::getMode() const
{
    return radioButtonPermanent->isChecked() ? Permanent : Temporary;
}

/****************************************************************************/

#if QT_VERSION < 0x050000
void ReplaceDialog::on_addressComboBox_textChanged()
#else
void ReplaceDialog::on_addressComboBox_currentTextChanged()
#endif
{
    okButton->setEnabled(!addressComboBox->currentText().isEmpty());
}

/****************************************************************************/

void ReplaceDialog::on_okButton_clicked()
{
    using QtPdCom::LoginManager;
    loginDialogShowed = false;

    if (newDataSource) {
        disconnect(newDataSource, &DataSource::variableTreeBuilt, this, &ReplaceDialog::connected);
        disconnect(newDataSource, &DataSource::error, this, &ReplaceDialog::error);
        newDataSource->disconnectFromHost();
        delete newDataSource;
        newDataSource = nullptr;
    }

    url = QUrl(addressComboBox->currentText());
    if (url.scheme() != "msr") {
        labelMessage->setText(tr("Unsupported scheme."));
        return;
    }
    if (url.port() == -1) {
        url.setPort(2345);
    }

    newDataSource = new DataSource(dataModel, dataSource->getUrl(), url);


    connect(newDataSource, &DataSource::variableTreeBuilt, this, &ReplaceDialog::connected);
    connect(newDataSource, &DataSource::error, this, &ReplaceDialog::error);
    newDataSource->credentialsNeededAction =  connect(
            newDataSource->getLoginManager(), &LoginManager::needCredentials,
            this, &ReplaceDialog::credentialsNeeded);
    connect(newDataSource->getLoginManager(), &LoginManager::loginFailed,
            this, &ReplaceDialog::onLoginFailed);
    connect(newDataSource->getLoginManager(), &LoginManager::loginSuccessful,
            this, [this] {
                if (cbUseAuth->isChecked() && loginDialogShowed)
                    accept();
            });

    okButton->setEnabled(false);
    addressComboBox->setEnabled(false);
    labelMessage->setText(tr("Connecting to %1...").arg(url.toString()));

    newDataSource->connectToHost();
}

/****************************************************************************/

void ReplaceDialog::on_cancelButton_clicked()
{
    if (newDataSource) {
        newDataSource->disconnectFromHost();
        newDataSource->deleteLater();
        newDataSource = NULL;
    }

    reject();
}

/****************************************************************************/

void ReplaceDialog::connected()
{
    QSettings settings;

    recentSources.removeAll(url.toString());
    recentSources.prepend(url.toString());

    settings.setValue("recentSources", recentSources);

    if (cbUseAuth->isChecked() && !loginDialogShowed)
        newDataSource->getLoginManager()->login();
    else
        accept();
}

/****************************************************************************/

void ReplaceDialog::error()
{
    labelMessage->setText("");

    auto* mb = new QMessageBox("Connection failed",
                tr("Failed to connect to %1: %2.")
                .arg(url.toString(), 1)
                .arg(newDataSource->errorString(), 2),
                QMessageBox::Critical,
                QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton,
                this);

    connect(mb, &QDialog::finished, mb, &QObject::deleteLater);
    mb->open();

    okButton->setEnabled(true);
    addressComboBox->setEnabled(true);
}

/****************************************************************************/

void ReplaceDialog::credentialsNeeded()
{
    auto dialog = new LoginDialog(*newDataSource->getLoginManager(), this);
    connect(dialog, &QDialog::finished, dialog, &QObject::deleteLater);
    connect(dialog, &QDialog::rejected, this, &QDialog::reject);
    dialog->show();
    loginDialogShowed = true;
}

/****************************************************************************/

void ReplaceDialog::onLoginFailed()
{

    labelMessage->setText("");

    QMessageBox("Login failed",
                tr("Login failed, invalid username or password."),
                QMessageBox::Critical,
                QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton,
                this).exec();

    okButton->setEnabled(true);
    addressComboBox->setEnabled(true);
    cbUseAuth->setEnabled(true);
}

/****************************************************************************/
