/* PlaylistCreator.cpp */
/*
 * Copyright (C) 2011-2024 Michael Lugmair
 *
 * This file is part of sayonara player
 *
 * This program 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.

 * This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "LocalPathPlaylistCreator.h"
#include "LocalPathProcessor.h"

#include "Utils/FileUtils.h"
#include "Utils/Language/Language.h"
#include "Utils/MetaData/MetaDataList.h"
#include "Utils/Settings/Settings.h"

#include <QStringList>
#include <atomic>

#include "Utils/Logger/Logger.h"

struct SplittedPaths
{
	QStringList standardPaths;
	QStringList playlistFiles;
};

namespace
{
	SplittedPaths splitPathlist(const QStringList& paths)
	{
		SplittedPaths result;
		for(const auto& path: paths)
		{
			if(Util::File::isSoundFile(path) || Util::File::isDir(path))
			{
				result.standardPaths << path;
			}

			else if(Util::File::isPlaylistFile(path))
			{
				result.playlistFiles << path;
			}
		}

		return result;
	}

	QString getPureFilename(const QString& filename)
	{
		const auto result = Util::File::getFilenameOfPath(filename);
		const auto lastDot = result.lastIndexOf('.');
		return (lastDot > 0)
		       ? result.left(lastDot)
		       : result;
	}

	int playlistsToCreate(const bool hasStandardPaths, const int playlistFiles)
	{
		return (hasStandardPaths ? 1 : 0) + playlistFiles;
	}
}

namespace Playlist
{
	class LocalPathPlaylistCreatorImpl :
		public LocalPathPlaylistCreator
	{
		Q_OBJECT

		public:
			explicit LocalPathPlaylistCreatorImpl(Creator* playlistCreator) :
				m_playlistCreator {playlistCreator} {}

			~LocalPathPlaylistCreatorImpl() override = default;

			void createPlaylists(const QStringList& paths, const QString& name, const bool temporary) override
			{
				spLog(Log::Debug, this) << "createPlaylists " << paths.size() << " paths";
				m_createdPlaylists.clear();

				const auto [standardPaths, playlistFiles] = splitPathlist(paths);
				m_playlistCount = playlistsToCreate(not standardPaths.isEmpty(), playlistFiles.count());

				if(!standardPaths.isEmpty())
				{
					m_createdPlaylists << createSinglePlaylist(standardPaths, name, temporary);
				}

				for(const auto& playlistFile: playlistFiles)
				{
					const auto playlistName = getPureFilename(playlistFile);
					const auto playlistFiles = QStringList() << playlistFile;

					m_createdPlaylists << createSinglePlaylist(playlistFiles, playlistName, true);
				}
			}

			QList<QPair<int, int>> createdPlaylists() const override { return m_createdPlaylists; }

		private: // NOLINT(readability-redundant-access-specifiers)
			QPair<int, int> createSinglePlaylist(const QStringList& paths, const QString& name, const bool temporary)
			{
				const auto playlistIndex = m_playlistCreator->createPlaylist(MetaDataList {}, name, temporary);

				auto* localPathProcessor = new LocalPathProcessor(m_playlistCreator->playlist(playlistIndex));

				connect(localPathProcessor, &LocalPathProcessor::sigFinished, this, [&]() {
					spLog(Log::Debug, this) << "single playlist created: " << playlistIndex << ", yet " << (m_playlistCount - 1) << " left";
					if((--m_playlistCount) == 0)
					{
						emit sigAllPlaylistsCreated();
					}
				});

				connect(localPathProcessor, &LocalPathProcessor::sigFinished, localPathProcessor, &QObject::deleteLater);

				const auto row = localPathProcessor->addPaths(paths);

				return {playlistIndex, row};
			}

			Creator* m_playlistCreator;
			std::atomic<int> m_playlistCount {0};
			QList<QPair<int, int>> m_createdPlaylists;
	};

	LocalPathPlaylistCreator* LocalPathPlaylistCreator::create(Creator* playlistCreator)
	{
		return new LocalPathPlaylistCreatorImpl(playlistCreator);
	}

	QString filesystemPlaylistName()
	{
		const auto createExtraPlaylist = GetSetting(Set::PL_CreateFilesystemPlaylist);
		if(!createExtraPlaylist)
		{
			return {};
		}

		const auto specifyPlaylistName = GetSetting(Set::PL_SpecifyFileystemPlaylistName);
		const auto specialPLaylistName = GetSetting(Set::PL_FilesystemPlaylistName);
		return (specialPLaylistName.trimmed().isEmpty() || specifyPlaylistName)
		       ? Lang::get(Lang::Files)
		       : specialPLaylistName;
	}
}

#include "LocalPathPlaylistCreator.moc"