/*
 * 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/.
 */

#pragma once

#include "Base/Utils.hpp"
#include <string_view>
#include <cinttypes>

namespace OpenVulkano
{
	class ShaderProgramType
	{
		static constexpr std::string_view FILE_EXTENSIONS_OPENGL[] = {
				".vert", ".tesc", ".tese", ".geom", ".frag", ".comp", ".mesh", ".task",
				".rgen", ".rahit", ".rchit", ".rmiss", ".rint", ".rcall", ".glsl"
		};

	public:
		enum Type : uint32_t {
			VERTEX = 1,
			TESSELLATION_CONTROL = 2,
			TESSELLATION_EVALUATION = 4,
			GEOMETRY = 8,
			FRAGMENT = 16,
			COMPUTE = 32,

			// Mesh shader
			MESH_TASK = 0x40,
			MESH_MESH = 0x80,

			// Raytracing
			RAY_GEN = 0x100,
			RAY_ANY_HIT = 0x200,
			RAY_CLOSEST_HIT = 0x400,
			RAY_MISS = 0x800,
			RAY_INTERSECTION = 0x1000,
			RAY_CALLABLE = 0x2000,

			ALL_GRAPHICS = 0x0000001F
		};

		ShaderProgramType(Type type) : m_type(type) {}

		[[nodiscard]] constexpr std::string_view GetExtensionOpenGL() const
		{
			return FILE_EXTENSIONS_OPENGL[GetId()];
		}

		[[nodiscard]] constexpr uint32_t GetId() const
		{
			if (m_type == ALL_GRAPHICS) return 14;
			return Utils::Log2OfPow2(static_cast<uint32_t>(m_type));
		}

		[[nodiscard]] bool operator ==(Type rhs) const
		{
			return m_type == rhs;
		}

		[[nodiscard]] bool operator !=(Type rhs) const
		{
			return m_type != rhs;
		}

		[[nodiscard]] operator uint32_t() const
		{
			return m_type;
		}

	private:
		Type m_type;
	};
}