/**********************************************************************
 * LeechCraft - modular cross-platform feature rich internet client.
 * Copyright (C) 2006-2014  Georg Rudoy
 *
 * Boost Software License - Version 1.0 - August 17th, 2003
 *
 * Permission is hereby granted, free of charge, to any person or organization
 * obtaining a copy of the software and accompanying documentation covered by
 * this license (the "Software") to use, reproduce, display, distribute,
 * execute, and transmit the Software, and to prepare derivative works of the
 * Software, and to permit third-parties to whom the Software is furnished to
 * do so, all subject to the following:
 *
 * The copyright notices in the Software and this entire statement, including
 * the above license grant, this restriction and the following disclaimer,
 * must be included in all copies of the Software, in whole or in part, and
 * all derivative works of the Software, unless such copies or derivative
 * works are solely in the form of machine-executable object code generated by
 * a source language processor.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
 * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
 * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 **********************************************************************/

#include "util.h"
#include <util/util.h>
#include <util/sll/qtutil.h>
#include <interfaces/lmp/mediainfo.h>

namespace LeechCraft
{
namespace LMP
{
	QMap<QString, std::function<QString (MediaInfo)>> GetSubstGetters ()
	{
		static const auto map = Util::MakeMap<QString, std::function<QString (MediaInfo)>> ({
				{ "$artist", [] (const MediaInfo& info) { return info.Artist_; } },
				{ "$album", [] (const MediaInfo& info) { return info.Album_; } },
				{ "$title", [] (const MediaInfo& info) { return info.Title_; } },
				{ "$year", [] (const MediaInfo& info) { return QString::number (info.Year_); } },
				{ "$trackNumber", [] (const MediaInfo& info) -> QString
					{
						auto trackNumStr = QString::number (info.TrackNumber_);
						if (info.TrackNumber_ < 10)
							trackNumStr.prepend ('0');
						return trackNumStr;
					} }
			});
		return map;
	}

	QMap<QString, std::function<void (MediaInfo&, QString)>> GetSubstSetters ()
	{
		static const auto map = Util::MakeMap<QString, std::function<void (MediaInfo&, QString)>> ({
				{ "$artist", [] (MediaInfo& info, const QString& val) { info.Artist_ = val; } },
				{ "$album", [] (MediaInfo& info, const QString& val) { info.Album_= val; } },
				{ "$title", [] (MediaInfo& info, const QString& val) { info.Title_ = val; } },
				{ "$year", [] (MediaInfo& info, const QString& val) { info.Year_ = val.toInt (); } },
				{ "$trackNumber", [] (MediaInfo& info, QString val)
					{
						if (val.size () == 2 && val.at (0) == '0')
							val = val.mid (1);
						info.TrackNumber_ = val.toInt ();
					} }
			});
		return map;
	}

	QStringList GetSubstGettersKeys ()
	{
		static const QStringList keys = GetSubstGetters ().keys ();
		return keys;
	}

	QString PerformSubstitutions (QString mask, const MediaInfo& info, SubstitutionFlags flags)
	{
		for (const auto& pair : Util::Stlize (GetSubstGetters ()))
		{
			auto value = pair.second (info);
			if (flags & SubstitutionFlag::SFSafeFilesystem)
				value.replace ('/', '_');
			mask.replace (pair.first, value);
		}

		if (flags & SubstitutionFlag::SFSafeFilesystem)
		{
			mask.replace ('?', '_');
			mask.replace ('*', '_');
		}

		return mask;
	}

	QStringList PerformSubstitutions (const QString& pattern,
			const QList<MediaInfo>& infos,
			const std::function<void (int, QString)>& setter,
			SubstitutionFlags flags)
	{
		QStringList names;

		const bool hasExtension = pattern.contains ('.');

		int row = 0;
		for (const auto& info : infos)
		{
			auto name = PerformSubstitutions (pattern, info, flags);
			if (!hasExtension)
				name += '.' + info.LocalPath_.section ('.', -1);

			names << name;

			setter (row++, name);
		}

		return names;
	}
}
}
