/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 */

#include "ArchiveConfiguration.hpp"
#include "Base/Utils.hpp"
#include <archive.h>

namespace OpenVulkano
{
	namespace
	{
		constexpr int TYPE_MAP[] = { ARCHIVE_FORMAT_TAR, ARCHIVE_FORMAT_CPIO, ARCHIVE_FORMAT_ISO9660, ARCHIVE_FORMAT_ZIP, ARCHIVE_FORMAT_XAR, ARCHIVE_FORMAT_7ZIP, ARCHIVE_FORMAT_WARC, ARCHIVE_FORMAT_SHAR };

		constexpr int COMP_MAP[] = { ARCHIVE_FILTER_COMPRESS, ARCHIVE_FILTER_NONE, ARCHIVE_FILTER_GZIP, ARCHIVE_FILTER_BZIP2, ARCHIVE_FILTER_XZ, ARCHIVE_FILTER_LZ4, ARCHIVE_FILTER_ZSTD };
		constexpr std::string_view COMP_NAMES[] = { ".Z", "", ".gz", ".bz2", ".xz", ".lz", ".zst" };

		constexpr std::string_view TAR_SORTS[] = { ".tZ", ".tar", ".tgz", ".tbz2", ".txz", ".tlz", ".tzst" };
	}

	std::string ArchiveConfiguration::GetFileExtension() const
	{
		const std::string_view tName = type.GetExtension();
		if (type == ArchiveType::TAR)
		{
			const std::string_view& cName = COMP_NAMES[static_cast<int>(compression)];
			std::string extension;
			extension.reserve(tName.length() + cName.length());
			extension.append(tName).append(cName);
			return extension;
		}
		return std::string(tName);
	}

	ArchiveConfiguration ArchiveConfiguration::FromFileName(const char* fileName)
	{
		std::string_view fName = fileName;
		ArchiveConfiguration ac;
		if (auto type = ArchiveType::FromExtension(fName))
		{
			ac.type = *type;
			return ac;
		}
		int tId = 0;
		for(const std::string_view& tsName : TAR_SORTS)
		{
			if (Utils::EndsWith(fName, tsName))
			{
				ac.compression = static_cast<CompressionType>(tId);
				return ac;
			}
			tId++;
		}
		tId = 0;
		for(const std::string_view& cName : COMP_NAMES)
		{
			std::string tName(".tar");
			tName.append(cName);
			if (Utils::EndsWith(fName, tName))
			{
				ac.compression = static_cast<CompressionType>(tId);
				return ac;
			}
			tId++;
		}
		return ac;
	}

	int ArchiveConfiguration::GetLibArchiveArchiveType() const
	{
		return TYPE_MAP[static_cast<int>(type)];
	}

	int ArchiveConfiguration::GetLibArchiveCompressionType() const
	{
		return COMP_MAP[static_cast<int>(compression)];
	}
}