/*
 * Fooyin
 * Copyright © 2024, Luke Taylor <luket@pm.me>
 *
 * Fooyin 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.
 *
 * Fooyin 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 Fooyin.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "saveplaylistsdialog.h"

#include "internalguisettings.h"

#include <core/application.h>
#include <core/coresettings.h>
#include <core/internalcoresettings.h>
#include <core/playlist/playlisthandler.h>
#include <core/playlist/playlistloader.h>
#include <core/playlist/playlistparser.h>
#include <utils/settings/settingsmanager.h>
#include <utils/utils.h>

#include <QComboBox>
#include <QDialogButtonBox>
#include <QFile>
#include <QFileDialog>
#include <QLabel>
#include <QMainWindow>
#include <QPushButton>
#include <QVBoxLayout>

using namespace Qt::StringLiterals;

namespace Fooyin {
SavePlaylistsDialog::SavePlaylistsDialog(Application* core, QWidget* parent)
    : QDialog{parent}
    , m_core{core}
    , m_settings{core->settingsManager()}
    , m_formats{new QComboBox(this)}
{
    const auto extensions = m_core->playlistLoader()->supportedSaveExtensions();
    for(const QString& ext : extensions) {
        m_formats->addItem(ext);
    }

    auto* formatLabel = new QLabel(tr("Playlist file format") + ":"_L1, this);

    auto* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
    QObject::connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
    QObject::connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);

    auto* layout = new QVBoxLayout(this);
    layout->addWidget(formatLabel);
    layout->addWidget(m_formats);
    layout->addWidget(buttonBox);
}

void SavePlaylistsDialog::accept()
{
    FyStateSettings stateSettings;

    const QString dir = stateSettings.value(Settings::Gui::Internal::LastPlaylistPath, QDir::homePath()).toString();

    QLoggingCategory log{"fy.saveplaylists"};

    const auto saveDir = QFileDialog::getExistingDirectory(Utils::getMainWindow(), tr("Select Directory"), dir,
                                                           QFileDialog::DontResolveSymlinks);
    if(saveDir.isEmpty()) {
        qCInfo(log) << "Could not save playlists: Invalid directory";
        QDialog::accept();
        return;
    }

    stateSettings.setValue(Settings::Gui::Internal::LastPlaylistPath, saveDir);

    const QString extension = m_formats->currentText();
    if(extension.isEmpty()) {
        qCInfo(log) << "Could not save playlists: Invalid format";
        QDialog::accept();
        return;
    }

    auto* parser = m_core->playlistLoader()->parserForExtension(extension);
    if(!parser) {
        qCInfo(log) << "Could not save playlists: No parser found for" << extension;
        QDialog::accept();
        return;
    }

    const auto playlists = m_core->playlistHandler()->playlists();
    for(const auto* playlist : playlists) {
        if(playlist->isTemporary() || playlist->trackCount() == 0) {
            continue;
        }

        const QString filepath = u"%1/%2.%3"_s.arg(saveDir, playlist->name(), extension);
        QFile playlistFile{QDir::cleanPath(filepath)};
        if(!playlistFile.open(QIODevice::WriteOnly)) {
            qCWarning(log) << "Could not open playlist file" << filepath
                           << "for writing:" << playlistFile.errorString();
            QDialog::accept();
            return;
        }

        const QFileInfo info{playlistFile};
        const QDir playlistDir{info.absolutePath()};
        const auto pathType = static_cast<PlaylistParser::PathType>(
            m_settings->fileValue(Settings::Core::Internal::PlaylistSavePathType, 0).toInt());
        const bool writeMetadata
            = m_settings->fileValue(Settings::Core::Internal::PlaylistSaveMetadata, false).toBool();

        parser->savePlaylist(&playlistFile, extension, playlist->tracks(), playlistDir, pathType, writeMetadata);
    }

    QDialog::accept();
}
} // namespace Fooyin
