/*
 * 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 "Scene/Drawable.hpp"
#include "Scene/UniformBuffer.hpp"
#include "Math/AABB.hpp"
#include "Scene/TextDrawable.hpp"
#include <list>

namespace OpenVulkano::Scene
{
	class Shader;

	struct LabelDrawableSettings
	{
		Math::Vector4f backgroundColor = { 1, 0, 0, 1 };
		Math::Vector2f padding = { 0.2f, 0.2f };
		float cornerRadius = 0.05f;
		float arrowLength = 0.5f;
		float arrowWidth = 0.2f;
		float scale = 1.0f;
		bool hasRoundedCorners = false;
		bool hasArrow = false;
		bool isBillboard = false;
	};
	
	struct LabelUniformData
	{
		Math::Vector4f color = { 0, 0, 0, 0 };
		Math::Vector2f textSize = {};
		Math::Vector2f bboxCenter = {};
		float cornerRadius = 0.f;
		float arrowLength = 0.f;
		float arrowWidth = 0.f;
		int32_t hasRoundedCorners = false;
		int32_t hasArrow = false;
		int32_t isBillboardFixedSize = false;
	};

	class LabelDrawable final : public Drawable
	{
	public:
		LabelDrawable(const std::shared_ptr<FontAtlas>& atlasData, const LabelDrawableSettings& settings = LabelDrawableSettings());

		void AddText(const std::string& text, const TextConfig& config = TextConfig());
		void SetLabelSettings(const LabelDrawableSettings& settings);
		void SetPosition(const Math::Vector2f& pos) { m_position = pos; }

		[[nodiscard]] std::list<TextDrawable>& GetTexts() { return m_texts; }
		[[nodiscard]] LabelDrawableSettings& GetSettings() { return m_settings; }
		[[nodiscard]] UniformBuffer* GetLabelBuffer() { return &m_labelBuffer; }
		[[nodiscard]] Math::Vector2f& GetPosition() { return m_position; }
		[[nodiscard]] bool IsBillboard() const { return m_settings.isBillboard; }
		[[nodiscard]] const Math::AABB2f& GetBoundingBox() const { return m_bbox; }

		[[nodiscard]] std::optional<RayHit> Intersect(const Ray& ray) const override;

	private:
		LabelDrawableSettings m_settings;
		std::shared_ptr<FontAtlas> m_atlasData;
		UniformBuffer m_labelBuffer;
		LabelUniformData m_labelData;
		std::list<TextDrawable> m_texts; // Using list instead of vector for stable iterators
		Math::Vector2f m_position = { 0, 0 };
		Math::AABB2f m_bbox;
	};
}
