#include <QCoreApplication>
#include <QCommandLineParser>
#include <QCommandLineOption>
#include <QImageReader>
#include <QImageWriter>
#include <QFile>
#include <QDebug>

#include "fitsdata.h"
#include "raw.h"
#include "common_formats.h"

int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);
    app.setApplicationVersion("2.0");

    QCommandLineParser parser;

    parser.setApplicationDescription("Small StellarMate OS tool to process FITS/XISF/RAW files.");
    parser.addVersionOption();
    parser.addHelpOption();

    parser.addPositionalArgument("file", "Source FITS/XISF/RAW file");
    parser.addOption(QCommandLineOption("q", "JPEG quality.", "quality", "100"));
    parser.addOption(QCommandLineOption("f", "Generated output format", "format", "jpg"));
    parser.addOption(QCommandLineOption("max-width", "Maximum output width", "width"));
    parser.addOption(QCommandLineOption("save-preview", "Generate preview.", "file"));
    parser.addOption(QCommandLineOption("save-thumb", "Generate thumb.", "file"));
    parser.addOption(QCommandLineOption("meta", "Generate metadata."));

    parser.process(app);

    const QStringList RAWFormats = { "cr2", "cr3", "crw", "nef", "raf", "dng", "arw"};
    const QStringList FITSFormats = { "fits", "fit", "fz", "xisf" };

    QStringList positionalArgs = parser.positionalArguments();

    if (positionalArgs.empty())
    {
        qCritical() << parser.helpText();
        return -1;
    }

    QString filename = positionalArgs[0];
    if (!QFile::exists(filename))
    {
        qCritical() << "File" << filename << "is not found!";
        return -1;
    }

    const QString sourceFormat = filename.mid(filename.lastIndexOf(".") + 1).toLower();
    const bool isRAW = RAWFormats.contains(sourceFormat);
    const bool isFITS = FITSFormats.contains(sourceFormat);
    const bool isCommon = QImageReader::supportedImageFormats().contains(sourceFormat.toLatin1());

    QString format = "jpg";
    if (parser.isSet("f"))
        format = parser.value("f");

    int quality = 80;
    if (parser.isSet("q"))
    {
        bool ok = false;
        int value = parser.value("q").toInt(&ok);
        if (ok)
            quality = value;
    }

    // 0 means do not resize, use hte original image width as is
    int maxWidth = 0;
    if (parser.isSet("max-width"))
    {
        bool ok = false;
        int value = parser.value("max-width").toInt(&ok);
        if (ok)
            maxWidth = value;
    }

    if (parser.isSet("meta"))
    {
        QByteArray metadata;

        if (isRAW)
        {
            metadata = RAW::metadata(filename);
        }
        else if (isFITS)
        {
            FITSData image;
            QFuture<bool> result = image.loadFromFile(filename);
            result.waitForFinished();
            metadata = image.metadata();
        }
        else if (isCommon)
        {
            metadata = CommonFormats::metadata(filename);
        }
        else
        {
            return -1;
        }

        QTextStream out(stdout);
        out << metadata;
    }
    else if (parser.isSet("save-preview"))
    {
        const QString output = parser.value("save-preview");
        QImage preview;

        if (isRAW)
            preview = RAW::toImage(filename, maxWidth, quality);
        else if (isFITS)
            preview = FITSData::FITSToImage(filename, maxWidth, quality);
        else if (isCommon)
            preview = CommonFormats::toImage(filename, maxWidth, quality);
        else
            return -1;

        if (preview.isNull())
        {
            qCritical() << "Failed to load or process image from" << filename;
            return -1;
        }

        QImageWriter writer(output);
        writer.setFormat(format.toLatin1());
        writer.setQuality(quality);
        if (!writer.write(preview))
        {
            qCritical() << "Failed to save preview to" << output << ":" << writer.errorString();
            QFile::remove(output);
            return -1;
        }
    }
    else if (parser.isSet("save-thumb"))
    {
        const QString output = parser.value("save-thumb");
        QImage preview;

        if (isRAW)
            preview = RAW::toImage(filename, 100, quality);
        else if (isFITS)
            preview = FITSData::FITSToImage(filename, 100, quality);
        else if (isCommon)
            preview = CommonFormats::toImage(filename, 100, quality);
        else
            return -1;

        if (preview.isNull())
        {
            qCritical() << "Failed to load or process image from" << filename;
            return -1;
        }

        QImageWriter writer(output);
        writer.setFormat(format.toLatin1());
        writer.setQuality(quality);
        if (!writer.write(preview))
        {
            qCritical() << "Failed to save thumbnail to" << output << ":" << writer.errorString();
            QFile::remove(output);
            return -1;
        }
    }

    return 0;
}
