/*  Multimodal Image Segmentation Tool (MIST)  */
/*  Eelke Visser  */

/*  Copyright (c) 2016 University of Oxford  */

/*  CCOPYRIGHT  */

#include "setupfilenameswindow.h"
#include "ui_setupfilenameswindow.h"
#include <QSettings>
#include <cstdlib>
#include <string>

// NB: QT will not show the dialog if it doesn't fit on the screen!

SetupFilenamesWindow::SetupFilenamesWindow(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::SetupFilenamesWindow)
{
    ui->setupUi(this);
    setWindowFlags(Qt::WindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint |
                                   Qt::WindowCloseButtonHint));

    std::string lastselected = LoadConfigurations();

    for (const auto &t : m_configurations)
    {
        ui->configurationComboBox->addItem(t.first.c_str());
        if (t.first == lastselected)
            ui->configurationComboBox->setCurrentIndex(ui->configurationComboBox->count() - 1);
    }
}

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

std::string SetupFilenamesWindow::LoadConfigurations()
{
    m_configurations.clear();

    QSettings settings;
    int configurations = settings.beginReadArray("NewConfigurations");
    for (int i = 0; i < configurations; i++)
    {
        settings.setArrayIndex(i);
        Configuration config;
        config.modelFilename = settings.value("Model").toString().toStdString();
        config.transformFilename = settings.value("Transformation").toString().toStdString();
        config.displacementsBasename = settings.value("Displacements").toString().toStdString();
        config.normExclusionFilename = settings.value("NormalisationExclusionMask").toString().toStdString();
        config.outputFilename = settings.value("Output").toString().toStdString();
        config.extraShapeFilename = settings.value("ExtraShape").toString().toStdString();
        config.overlayFilename = settings.value("Overlay").toString().toStdString();

        int modalities = settings.beginReadArray("Modalities");
        for (int j = 0; j < modalities; j++)
        {
            settings.setArrayIndex(j);
            config.volumeFilenames[settings.value("ModalityName").toString().toStdString()] =
                    settings.value("ModalityVolume").toString().toStdString();
        }

        settings.endArray();
        m_configurations[settings.value("Name").toString().toStdString()] = config;
    }

    settings.endArray();

    int shapes = settings.beginReadArray("MultiShape");
    ui->multiShapeTable->setRowCount(shapes);

    for (int i = 0; i < shapes; i++)
    {
        settings.setArrayIndex(i);
        ui->multiShapeTable->setItem(i, 0, new QTableWidgetItem(settings.value("Filename").toString()));
        ui->multiShapeTable->setItem(i, 1, new QTableWidgetItem(settings.value("DisplacementsBasename").toString()));
        ui->multiShapeTable->setItem(i, 2, new QTableWidgetItem(std::to_string(settings.value("Red").toFloat()).c_str()));
        ui->multiShapeTable->setItem(i, 3, new QTableWidgetItem(std::to_string(settings.value("Green").toFloat()).c_str()));
        ui->multiShapeTable->setItem(i, 4, new QTableWidgetItem(std::to_string(settings.value("Blue").toFloat()).c_str()));
    }

    settings.endArray();

    return settings.value("LastSelected").toString().toStdString();
}

void SetupFilenamesWindow::SaveConfigurations(const std::string &selected)
{
    QSettings settings;

    settings.beginWriteArray("NewConfigurations");
    settings.remove("");
    int i = 0;
    for (const auto &t : m_configurations)
    {
        settings.setArrayIndex(i++);
        settings.setValue("Name", t.first.c_str());

        const Configuration &config = t.second;
        settings.setValue("Model", config.modelFilename.c_str());
        settings.setValue("Transformation", config.transformFilename.c_str());
        settings.setValue("Displacements", config.displacementsBasename.c_str());
        settings.setValue("NormalisationExclusionMask", config.normExclusionFilename.c_str());
        settings.setValue("Output", config.outputFilename.c_str());
        settings.setValue("ExtraShape", config.extraShapeFilename.c_str());
        settings.setValue("Overlay", config.overlayFilename.c_str());

        settings.beginWriteArray("Modalities");
        int j = 0;
        for (const auto &s : config.volumeFilenames)
        {
            settings.setArrayIndex(j++);
            settings.setValue("ModalityName", s.first.c_str());
            settings.setValue("ModalityVolume", s.second.c_str());
        }

        settings.endArray();
    }

    settings.endArray();

    settings.beginWriteArray("MultiShape");
    for (int i = 0; i < ui->multiShapeTable->rowCount(); i++)
    {
        settings.setArrayIndex(i);
        settings.setValue("Filename", ui->multiShapeTable->item(i, 0)->text());
        settings.setValue("DisplacementsBasename", ui->multiShapeTable->item(i, 1)->text());
        settings.setValue("Red", std::atof(ui->multiShapeTable->item(i, 2)->text().toStdString().c_str()));
        settings.setValue("Green", std::atof(ui->multiShapeTable->item(i, 3)->text().toStdString().c_str()));
        settings.setValue("Blue", std::atof(ui->multiShapeTable->item(i, 4)->text().toStdString().c_str()));
    }
    settings.endArray();

    settings.setValue("LastSelected", selected.c_str());
    settings.sync();
}

void SetupFilenamesWindow::ShowConfiguration(const std::string &name)
{
    if (!name.empty())
    {
        const Configuration &config = m_configurations.find(name)->second;

        ui->modelFilenameLineEdit->setText(config.modelFilename.c_str());
        ui->transformationFilenameLineEdit->setText(config.transformFilename.c_str());
        ui->displacementsBasenameLineEdit->setText(config.displacementsBasename.c_str());
        ui->normExclusionFilenameLineEdit->setText(config.normExclusionFilename.c_str());
        ui->outputFilenameLineEdit->setText(config.outputFilename.c_str());
        ui->extraShapeFilenameLineEdit->setText(config.extraShapeFilename.c_str());
        ui->overlayFilenameLineEdit->setText(config.overlayFilename.c_str());

        ui->volumeFilenameTable->setRowCount(config.volumeFilenames.size());
        int i = 0;
        for (const auto &t : config.volumeFilenames)
        {
            ui->volumeFilenameTable->setItem(i, 0, new QTableWidgetItem(t.first.c_str()));
            ui->volumeFilenameTable->setItem(i, 1, new QTableWidgetItem(t.second.c_str()));
            i++;
        }
    }
}

void SetupFilenamesWindow::EmptyConfiguration()
{
    ui->modelFilenameLineEdit->clear();
    ui->transformationFilenameLineEdit->clear();
    ui->displacementsBasenameLineEdit->clear();
    ui->normExclusionFilenameLineEdit->clear();
    ui->outputFilenameLineEdit->clear();
    ui->extraShapeFilenameLineEdit->clear();
    ui->overlayFilenameLineEdit->clear();

    ui->volumeFilenameTable->setRowCount(0);
}

void SetupFilenamesWindow::on_configurationComboBox_currentIndexChanged(const QString &text)
{
    ShowConfiguration(text.toStdString());
}

void SetupFilenamesWindow::on_deleteButton_clicked()
{
    auto match = m_configurations.find(ui->configurationComboBox->currentText().toStdString());
    if (match != m_configurations.end())
    {
        m_configurations.erase(match);
        ui->configurationComboBox->removeItem(ui->configurationComboBox->currentIndex());
    }
    else if (ui->configurationComboBox->count())
    {
        ui->configurationComboBox->setCurrentIndex(0);
    }
    else
    {
        ui->configurationComboBox->clearEditText();
        EmptyConfiguration();
    }
}

void SetupFilenamesWindow::accept()
{
    // This ensures that any open editors on the QTableWidget / QComboBox(?) are closed ...
    ui->buttonBox->setFocus();

    std::string selected = ui->configurationComboBox->currentText().toStdString();
    if (!selected.empty())
    {
        Configuration config;
        config.modelFilename = ui->modelFilenameLineEdit->text().toStdString();
        config.transformFilename = ui->transformationFilenameLineEdit->text().toStdString();
        config.displacementsBasename = ui->displacementsBasenameLineEdit->text().toStdString();
        config.normExclusionFilename = ui->normExclusionFilenameLineEdit->text().toStdString();
        config.outputFilename = ui->outputFilenameLineEdit->text().toStdString();
        config.extraShapeFilename = ui->extraShapeFilenameLineEdit->text().toStdString();
        config.overlayFilename = ui->overlayFilenameLineEdit->text().toStdString();

        for (int i = 0; i < ui->volumeFilenameTable->rowCount(); i++)
            config.volumeFilenames[ui->volumeFilenameTable->item(i, 0)->text().toStdString()] =
                    ui->volumeFilenameTable->item(i, 1)->text().toStdString();

        m_configurations[ui->configurationComboBox->currentText().toStdString()] = config;

        SaveConfigurations(selected);
    }
    else if (m_configurations.empty())
        SaveConfigurations(std::string());
    else
        SaveConfigurations(m_configurations.cbegin()->first);

    QDialog::accept();
}

int SetupFilenamesWindow::GetNumberOfVolumes() const
{
    return ui->volumeFilenameTable->rowCount();
}

void SetupFilenamesWindow::GetVolumeFilename(int i, std::string& name, std::string& filename)
{
    if (i < ui->volumeFilenameTable->rowCount())
    {
        name = ui->volumeFilenameTable->item(i, 0)->text().toStdString();
        filename = ui->volumeFilenameTable->item(i, 1)->text().toStdString();
    }
    else
    {
        name = std::string();
        filename = std::string();
    }
}

std::string SetupFilenamesWindow::GetModelFilename() const
{
    return ui->modelFilenameLineEdit->text().toStdString();
}

std::string SetupFilenamesWindow::GetTransformFilename() const
{
    return ui->transformationFilenameLineEdit->text().toStdString();
}

std::string SetupFilenamesWindow::GetDisplacementsBasename() const
{
    return ui->displacementsBasenameLineEdit->text().toStdString();
}

std::string SetupFilenamesWindow::GetNormExclusionFilename() const
{
    return ui->normExclusionFilenameLineEdit->text().toStdString();
}

std::string SetupFilenamesWindow::GetOutputFilename() const
{
    return ui->outputFilenameLineEdit->text().toStdString();
}

std::string SetupFilenamesWindow::GetExtraShapeFilename() const
{
    return ui->extraShapeFilenameLineEdit->text().toStdString();
}

std::string SetupFilenamesWindow::GetOverlayFilename() const
{
    return ui->overlayFilenameLineEdit->text().toStdString();
}

int SetupFilenamesWindow::GetNumberOfShapes() const
{
    return ui->multiShapeTable->rowCount();
}

void SetupFilenamesWindow::GetShape(int i, std::string &filename, std::string &displacementsbasename, float &red, float &green, float &blue) const
{
    if (i < ui->multiShapeTable->rowCount())
    {
        filename = ui->multiShapeTable->item(i, 0)->text().toStdString();
        displacementsbasename = ui->multiShapeTable->item(i, 1)->text().toStdString();
        red = std::atof(ui->multiShapeTable->item(i, 2)->text().toStdString().c_str());
        green = std::atof(ui->multiShapeTable->item(i, 3)->text().toStdString().c_str());
        blue = std::atof(ui->multiShapeTable->item(i, 4)->text().toStdString().c_str());
    }
    else
    {
        filename = std::string();
        displacementsbasename = std::string();
        red = 0.0;
        green = 0.0;
        blue = 0.0;
    }
}

void SetupFilenamesWindow::on_addButton_clicked()
{
    int row = ui->volumeFilenameTable->rowCount();
    ui->volumeFilenameTable->setRowCount(row + 1);
    ui->volumeFilenameTable->setItem(row, 0, new QTableWidgetItem());
    ui->volumeFilenameTable->setItem(row, 1, new QTableWidgetItem());
}

void SetupFilenamesWindow::on_removeButton_clicked()
{
    int index = ui->volumeFilenameTable->currentRow();
    if (index >= 0)
        ui->volumeFilenameTable->removeRow(index);
}

void SetupFilenamesWindow::on_multiShapeRemoveButton_clicked()
{
    int index = ui->multiShapeTable->currentRow();
    if (index >= 0)
        ui->multiShapeTable->removeRow(index);
}

void SetupFilenamesWindow::on_multiShapeAddButton_clicked()
{
    int row = ui->multiShapeTable->rowCount();
    ui->multiShapeTable->setRowCount(row + 1);
    ui->multiShapeTable->setItem(row, 0, new QTableWidgetItem());
    ui->multiShapeTable->setItem(row, 1, new QTableWidgetItem());
    ui->multiShapeTable->setItem(row, 2, new QTableWidgetItem());
    ui->multiShapeTable->setItem(row, 3, new QTableWidgetItem());
    ui->multiShapeTable->setItem(row, 4, new QTableWidgetItem());
}
