/*
 * SPDX-FileCopyrightText: 2019-2025 Mattia Basaglia <dev@dragon.best>
 *
 * SPDX-License-Identifier: GPL-3.0-or-later
 */

#include "export_image_sequence_dialog.hpp"
#include "ui_export_image_sequence_dialog.h"
#include <QEvent>
#include <QImageWriter>
#include <QMessageBox>
#include <QFileDialog>

#include "io/raster/raster_mime.hpp"
#include "io/svg/svg_renderer.hpp"
#include "math/math.hpp"

class glaxnimate::gui::ExportImageSequenceDialog::Private
{
public:
    Ui::ExportImageSequenceDialog ui;
    model::Composition* comp;
};

glaxnimate::gui::ExportImageSequenceDialog::ExportImageSequenceDialog(
    model::Composition* comp, QDir export_path, QWidget* parent
)
    : QDialog(parent), d(std::make_unique<Private>())
{
    d->comp = comp;
    if ( !export_path.exists() )
        export_path = comp->document()->io_options().path;

    d->ui.setupUi(this);
    auto frame_from = comp->animation->first_frame.get();
    auto frame_to = comp->animation->last_frame.get();
    d->ui.input_frame_from->setMinimum(frame_from);
    d->ui.input_frame_from->setMaximum(frame_to);
    d->ui.input_frame_from->setValue(frame_from);
    d->ui.input_frame_to->setMinimum(frame_from);
    d->ui.input_frame_to->setMaximum(frame_to);
    d->ui.input_frame_to->setValue(frame_to);
    d->ui.input_path->setText(export_path.path());

    for ( const auto& ext : QImageWriter::supportedImageFormats() )
    {
        if ( ext != "svg" && ext != "svgz" )
            d->ui.input_format->addItem("." + QString::fromUtf8(ext), QVariant(ext));
    }

    d->ui.input_format->addItem(".svg", QVariant(QByteArrayLiteral("svg")));
    d->ui.input_format->model()->sort(0);

    d->ui.input_format->setCurrentText(".png");

    d->ui.progress_bar->hide();
}

glaxnimate::gui::ExportImageSequenceDialog::~ExportImageSequenceDialog() = default;

QDir glaxnimate::gui::ExportImageSequenceDialog::export_path() const
{
    return d->ui.input_path->text();
}

void glaxnimate::gui::ExportImageSequenceDialog::render()
{
    auto path = export_path();
    if ( !path.exists() )
    {
        // Why isn't there an easier way?
        auto parent = path;
        parent.cdUp();
        if ( !parent.mkpath(path.dirName()) )
        {
            QMessageBox::critical(this, i18nc("@title:window", "Error"), i18nc("%1 path", "Could not create directory\n%1", path.path()));
            return;
        }
    }

    auto name_template = d->ui.input_name->text();
    auto ext = d->ui.input_format->currentText();
    auto format = d->ui.input_format->currentData().toByteArray();
    bool is_svg = format == "svg";

    auto frame_from = d->ui.input_frame_from->value();
    auto frame_to = d->ui.input_frame_to->value();
    auto frame_step = d->ui.input_frame_step->value();


    d->ui.progress_bar->setMinimum(frame_from);
    d->ui.progress_bar->setMaximum(frame_to);
    d->ui.progress_bar->setValue(frame_from);
    d->ui.progress_bar->show();

    auto max = std::max(std::abs(frame_from), std::abs(frame_to));
    auto pad = max != 0 ? std::ceil(std::log(max) / std::log(10)) : 1;
    for ( int f = frame_from; f < frame_to; f += frame_step )
    {
        QString frame_name = QString::number(f).rightJustified(pad, '0');
        QString basename = name_template;
        basename.append(ext);
        basename.replace("{frame}", frame_name);

        if ( is_svg )
        {
            io::svg::SvgRenderer rend(io::svg::NotAnimated, io::svg::CssFontType::FontFace);
            QFile file(path.filePath(basename));
            if ( file.open(QFile::WriteOnly) )
            {
                rend.write_main(d->comp, f);
                rend.write(&file, true);
            }
        }
        else
        {
            QImageWriter(path.filePath(basename), format).write(
                io::raster::RasterMime::frame_to_image(d->comp, f)
            );
        }

        d->ui.progress_bar->setValue(f);
    };

    accept();
}

void glaxnimate::gui::ExportImageSequenceDialog::pick_path()
{
    auto path = QFileDialog::getExistingDirectory(
        this,
        i18nc("@title:window", "Choose directory"),
        export_path().path(),
        QFileDialog::DontResolveSymlinks
    );
    if ( !path.isEmpty() )
        d->ui.input_path->setText(path);
}
