//  ************************************************************************************************
//
//  BornAgain: simulate and fit reflection and scattering
//
//! @file      GUI/View/PlotUtil/SavePlotAssistant.cpp
//! @brief     Implements class SavePlotAssistant
//!
//! @homepage  http://www.bornagainproject.org
//! @license   GNU General Public License v3 or higher (see COPYING)
//! @copyright Forschungszentrum Jülich GmbH 2018
//! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
//
//  ************************************************************************************************

#include "GUI/View/PlotUtil/SavePlotAssistant.h"
#include "Base/Util/Assert.h"
#include "Device/IO/IOFactory.h"
#include "GUI/Application/ApplicationSettings.h"
#include "GUI/View/PlotUtil/ColorMap.h"
#include <QFileDialog>
#include <QMessageBox>
#include <QVector>
#include <qcustomplot.h>
#include <utility>

namespace {

const QString png_extension = ".png";
const QString jpg_extension = ".jpg";
const QString pdf_extension = ".pdf";
const QString int_extension = ".int";
const QString tif_extension = ".tif";
const QString txt_extension = ".txt";

class Format {
public:
    Format() = default;
    Format(QString file_extention, QString filter);
    QString m_file_extention;
    QString m_filter;
};

Format::Format(QString file_extention, QString filter)
    : m_file_extention(std::move(file_extention))
    , m_filter(std::move(filter))
{
}

const QVector<Format> outFormats = {
    Format(png_extension, "png Image (*.png)"),
    Format(jpg_extension, "jpg Image (*.jpg)"),
    Format(pdf_extension, "pdf File (*.pdf)"),
    Format(int_extension, "BornAgain ASCII format (*.int)"),
    Format(txt_extension, "Simple ASCII table (*.txt)"),
#ifdef BA_TIFF_SUPPORT
    Format(tif_extension, "32-bits TIFF files (*.tif)"),
#endif
};

bool isPngFile(const QString& fileName)
{
    return fileName.endsWith(png_extension, Qt::CaseInsensitive);
}

bool isJpgFile(const QString& fileName)
{
    return fileName.endsWith(jpg_extension, Qt::CaseInsensitive);
}

bool isPdfFile(const QString& fileName)
{
    return fileName.endsWith(pdf_extension, Qt::CaseInsensitive);
}

void saveToFile(const QString& fileName, QCustomPlot* plot, const Datafield* output_data)
{
    if (isPngFile(fileName))
        plot->savePng(fileName);

    else if (isJpgFile(fileName))
        plot->saveJpg(fileName);

    else if (isPdfFile(fileName))
        plot->savePdf(fileName, plot->width(), plot->height());

    else {
        ASSERT(output_data);
        IO::writeDatafield(*output_data, fileName.toStdString());
    }
}

//! Returns string contraining all defined filters in the format suitable for QFileDialog
QString getFilterString()
{
    QString result;
    for (int i = 0; i < outFormats.size(); ++i) {
        result.append(outFormats[i].m_filter);
        if (i != outFormats.size() - 1)
            result.append(";;");
    }
    return result;
}

bool isValidExtension(const QString& fileName)
{
    for (int i = 0; i < outFormats.size(); ++i)
        if (fileName.endsWith(outFormats[i].m_file_extention, Qt::CaseInsensitive))
            return true;
    return false;
}

QString getExtensionFromFilterName(const QString& filterName)
{
    for (int i = 0; i < outFormats.size(); ++i)
        if (outFormats[i].m_filter == filterName)
            return outFormats[i].m_file_extention;
    return "";
}

//! Compose file name to save plot from information provided by QFileDialog
QString composeFileName(const QString& fileName, const QString& filterName)
{
    if (fileName.isEmpty() || filterName.isEmpty())
        return "";
    if (isValidExtension(fileName))
        return fileName;
    return fileName + getExtensionFromFilterName(filterName);
}

} // namespace


void GUI::Plot::savePlot(const QString& dirname, QCustomPlot* plot, const Datafield* output_data)

{
    QString selectedFilter("*.png");
    QString defaultName = dirname + "/untitled";
    QString fileName = QFileDialog::getSaveFileName(
        nullptr, "Save Plot", defaultName, getFilterString(), &selectedFilter,
        appSettings->useNativeFileDialog() ? QFileDialog::Options()
                                           : QFileDialog::DontUseNativeDialog);
    if (fileName.isEmpty())
        return;

    QString nameToSave = composeFileName(fileName, selectedFilter);
    try {
        saveToFile(nameToSave, plot, output_data);
    } catch (const std::exception& ex) {
        QString message = "Attempt to save file with the name '";
        message.append(nameToSave);
        message.append("' has failed with following error message\n\n");
        message.append(QString::fromStdString(ex.what()));
        QMessageBox::warning(nullptr, "Houston, we have a problem.", message);
    }
}
