// =====================================================================================================================
//  fennec, a free and open source game engine
//  Copyright © 2025 - 2026  Medusa Slockbower
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program.  If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================

///
/// \file fennec/scene/node2d.h
/// \brief
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 - 2026 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///

#ifndef FENNEC_SCENE_COMPONENTS_TRANSFORM2D_H
#define FENNEC_SCENE_COMPONENTS_TRANSFORM2D_H

#include <fennec/math/matrix.h>
#include <fennec/math/ext/transform.h>

#include <fennec/core/event.h>

#include <fennec/scene/scene_node.h>


namespace fennec
{

struct node2d;

struct transform_update_2d : event {
	node2d* node;

	FENNEC_RTTI_CLASS_ENABLE(event) {
	}
};

///
/// \brief 2D Scene Node
struct node2d : scene_node {
// Definitions =========================================================================================================

	///
	/// \brief Node Mobility
	enum mobility_ : bool {
		mobility_static = false, //!< Promise that this node won't have any transform changes.
		mobility_free   = true   //!< No transform restrictions.
	};


// Constructors & Destructor ===========================================================================================
public:

	///
	/// \brief Default Constructor, initializes an identity matrix.
	/// \details This is the default node2d constructor, for inheritance, use the typed constructor
	node2d(fennec::scene* scn, size_t id, const string& name)
		: scene_node(scn, id, name)
		, _mobility(mobility_free)
		, _position(0, 0)
		, _scale(1, 1)
		, _shear(0, 0)
		, _rotation(0) {
	}

	///
	/// \brief Default Typed Constructor, initializes an identity matrix with proper typing for inheritance.
	template<typename TypeT>
	node2d(fennec::scene* scn, size_t id, const string& name, TypeT* type)
		: scene_node(scn, id, name, type)
		, _mobility(mobility_free)
		, _position(0, 0)
		, _scale(1, 1)
		, _shear(0, 0)
		, _rotation(0) {
	}

	node2d(const node2d&) = default;
	node2d(node2d&&) noexcept = default;

	~node2d() = default;

// Access ==============================================================================================================

	constexpr const vec2& position() const {
		return _position;
	}

	constexpr const vec2& scale() const {
		return _scale;
	}

	constexpr float rotation() const {
		return _rotation;
	}

	constexpr const vec2& shear() const {
		return _shear;
	}

	constexpr bool mobility() const {
		return _mobility;
	}


// Modifiers ===========================================================================================================

	constexpr void translate(const vec2& x) {
		if (_mobility) {
			_position += x;
		}
	}

	constexpr void scale(const vec2& s) {
		if (_mobility) {
			_scale *= s;
		}
	}

	constexpr void rotate(float r) {
		if (_mobility) {
			_rotation += r;
		}
	}

	constexpr void shear(const vec2& s) {
		if (_mobility) {
			_shear += s;
		}
	}

	constexpr void apply() {
		if (not _mobility) {
			return;
		}

		// Get parent





		// Propagate down

	}

	constexpr const mat3& local() {
		return _local;
	}

	constexpr const mat3& global() {
		return _global;
	}

// Private Member Variables ============================================================================================
private:
	bool  _mobility;
	vec2  _position;
	vec2  _scale;
	vec2  _shear;
	float _rotation;
	mat3  _local, _global;


// Private Helpers =====================================================================================================

	constexpr void _recalculate(const mat3& parent) {
		_local  = fennec::rotation(_rotation);
		_local *= fennec::shear(_shear);
		_local *= fennec::scaling(_scale);
		_local *= fennec::translation(_position);
		_global = parent * _local;
	}
};

}


#endif // FENNEC_SCENE_COMPONENTS_TRANSFORM2D_H