#include "track/types.h"
#include "core/filesystem.h"
#include "core/json.h"
#include <fstream>
#include <vector>
#include <string>

using namespace nlohmann::literals::json_literals;

namespace Track {
namespace Types {

static nlohmann::json default_players = {
	{
		{"name", "VLC"},
#ifdef MACOSX
		{"executable", "VLC"},
#elif defined(WIN32)
		{"executable", "vlc.exe"},
#else
		{"executable", "vlc"},
#endif
		{"enabled", true}
	},
	{
		{"name", "mpv"},
#ifdef WIN32
		{"executable", "mpv.exe"},
#else
		{"executable", "mpv"},
#endif
		{"enabled", true}
	},
#ifdef WIN32
	{
		{"name", "MPC-HC x64"},
		{"executable", "mpc-hc64.exe"},
		{"enabled", true}
	},
	{
		{"name", "MPC-HC"},
		{"executable", "mpc-hc.exe"},
		{"enabled", true}
	},
	{
		{"name", "Windows Media Player"},
		{"executable", "wmplayer.exe"},
		{"enabled", true}
	}
#elif defined(MACOSX)
	{
		{"name", "IINA"},
		{"executable", "IINA"},
		{"enabled", true}
	},
	{
		{"name", "QuickTime Player"},
		{"executable", "QuickTime Player"},
		{"enabled", false}
	}
#else
	{
		{"name", "MPC-Qt"},
		{"executable", "mpc-qt"},
		{"enabled", true}
	}
#endif
};

static nlohmann::json default_extensions = {
	/* These are the four most common file extensions
	   according to... me. */
	{
		{"extension", "mkv"},
		{"enabled", true}
	},
	{
		{"extension", "mp4"},
		{"enabled", true}
	},
	{
		{"extension", "m4v"},
		{"enabled", true}
	},
	{
		{"extension", "avi"},
		{"enabled", true}
	},
	/* Matroska's retarded inbred cousin */
	{
		{"extension", "webm"},
		{"enabled", true}
	},
	/* QuickTime */
	{
		{"extension", "mov"},
		{"enabled", true}
	},
	{
		{"extension", "qt"},
		{"enabled", true}
	},
	/* MPEG transport stream */
	{
		{"extension", "mts"},
		{"enabled", true}
	},
	{
		{"extension", "m2ts"},
		{"enabled", true}
	},
	{
		{"extension", "ts"},
		{"enabled", true}
	},
	/* MPEG-1 */
	{
		{"extension", "mpg"},
		{"enabled", true}
	},
	{
		{"extension", "mpeg"},
		{"enabled", true}
	},
	{
		{"extension", "mpe"},
		{"enabled", true}
	},
	{
		{"extension", "mpv"},
		{"enabled", true}
	},
	/* MPEG-2 */
	{
		{"extension", "m2v"},
		{"enabled", true}
	},
	{
		{"extension", "mp2"},
		{"enabled", true}
	},
	/* 3GPP */
	{
		{"extension", "3gp"},
		{"enabled", true}
	},
	{
		{"extension", "3g2"},
		{"enabled", true}
	},
	/* Windows Media */
	{
		{"extension", "asf"},
		{"enabled", true}
	},
	{
		{"extension", "wmv"},
		{"enabled", true}
	},
	/* Adobe Flash */
	{
		{"extension", "flv"},
		{"enabled", true}
	},
	{
		{"extension", "swf"}, // lol
		{"enabled", false}
	},
	/* Ogg Video */
	{
		{"extension", "ogv"},
		{"enabled", true}
	},
	/* RealPlayer... LOL */
	{
		{"extension", "rm"},
		{"enabled", true}
	},
	{
		{"extension", "rmvb"},
		{"enabled", true}
	},
	/* Nullsoft Streaming Video (Winamp) */
	{
		{"extension", "nsv"},
		{"enabled", true}
	},
	/* Material Exchange Format (Sony) */
	{
		{"extension", "mxf"},
		{"enabled", true}
	},
};

void LoadPlayers(std::vector<MediaPlayer>& players) {
	nlohmann::json json;
	{	
		std::ifstream is(Filesystem::GetPlayersPath().GetPath());
		if (!is.is_open())
			json = default_players;
		else
			is >> json;
	}

	players.reserve(json.size());
	for (const auto& item : json) {
		MediaPlayer player;
		player.SetName(JSON::GetString(item, "/name"_json_pointer));
		player.SetExecutable(JSON::GetString(item, "/executable"_json_pointer));
		player.SetEnabled(JSON::GetBoolean(item, "/enabled"_json_pointer));
		players.push_back(player);
	}
}

void LoadExtensions(std::vector<MediaExtension>& extensions) {
	nlohmann::json json;
	{	
		std::ifstream is(Filesystem::GetExtensionsPath().GetPath());
		if (!is.is_open())
			json = default_extensions;
		else
			is >> json;
	}

	extensions.reserve(json.size());
	for (const auto& item : json) {
		MediaExtension extension;
		extension.SetExtension(JSON::GetString(item, "/extension"_json_pointer));
		extension.SetEnabled(JSON::GetBoolean(item, "/enabled"_json_pointer));
		extensions.push_back(extension);
	}
}

void SavePlayers(const std::vector<MediaPlayer>& players) {
	nlohmann::json json = {};
	for (const auto& player : players) {
		json.push_back({
			{"name", player.GetName()},
			{"executable", player.GetExecutable()},
			{"enabled", player.GetEnabled()}
		});
	}

	{
		std::ofstream os(Filesystem::GetPlayersPath().GetPath());
		if (!os.is_open())
			return;
		os << std::setw(4) << json << std::endl;
	}
}

void SaveExtensions(const std::vector<MediaExtension>& extensions) {
	nlohmann::json json = {};
	for (const auto& extension : extensions) {
		json.push_back({
			{"extension", extension.GetExtension()},
			{"enabled", extension.GetEnabled()}
		});
	}

	{
		std::ofstream os(Filesystem::GetExtensionsPath().GetPath());
		if (!os.is_open())
			return;
		os << std::setw(4) << json << std::endl;
	}
}

}
}
