/*
Crafter.Build
Copyright (C) 2025 Catcrafts®
Catcrafts.net

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3.0 of the License, or (at your option) any later version.

This library 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
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
*/

module;

#include <vector>
#include <algorithm>

export module Crafter.Component:ComponentRef;

import :Component;
import Crafter.Event;

namespace Crafter {
	export template <typename T>
	class ComponentRef {
	public:
		Event<T*> refChanged;
		Event<T*> componentDeleted;
		T* component;
		ComponentRef() : component(nullptr) {

		};

		ComponentRef(T* component) {
			SetRef(component);
		}

		virtual void SetRef(T* component) {
			if (component != nullptr) {
				onDeleteListener.SetEvent(&component->onDelete, [this, component]() {
					this->componentDeleted.Invoke(component);
				});
			}
			refChanged.Invoke(component);
			this->component = component;
		}
	protected:
		EventListener<void> onDeleteListener;
	};

	export template <typename T>
	class ComponentRefOwning : public ComponentRef<T> {
	public:
		ComponentRefOwning() : ComponentRef<T>() {

		};

		ComponentRefOwning(T* component) : ComponentRef<T>(component) {
			component->AddOwner();
		}
		~ComponentRefOwning() {
			if (ComponentRef<T>::component) {
				ComponentRef<T>::component->RemoveOwner();
			}
		}

		void SetRef(T* component) override {
			if (this->component != nullptr) {
				this->component->RemoveOwner();
			}

			if (component != nullptr) {
				ComponentRef<T>::onDeleteListener.SetEvent(&component->onDelete, [this, component]() {
					this->componentDeleted.Invoke(component);
				});
				component->AddOwner();
			}
			this->component = component;
		}
	};

	export template <typename T>
	class ComponentRefVector {
	public:
		Event<T*> componentRemoved;
		Event<T*> componentDeleted;
		Event<T*> componentAdded;
		std::vector<T*> components;

		ComponentRefVector() {

		}

		ComponentRefVector(std::vector<T*> components) : components(components) {

		}

		virtual void AddComponent(T* component) {
			componentAdded.Invoke(component);
			components.push_back(component);
			listeners.emplace_back(&component->onDelete, [this, component]() {
				this->componentDeleted.Invoke(component);
				components.erase(std::remove(components.begin(), components.end(), component), components.end());
			});
		}

		virtual void RemoveComponent(T* component) {
			componentRemoved.Invoke(component);
			auto it = find(components.begin(), components.end(), component);
			int index = it - components.begin();
			components.erase(components.begin() + index);
		}
	private:
		std::vector<EventListener<void>> listeners;
	};

	export template <typename T>
	class ComponentRefVectorOwning : public ComponentRefVector<T> {
	public:
		ComponentRefVectorOwning() {

		}

		ComponentRefVectorOwning(std::vector<T*> components) : ComponentRefVector<T>(components) {

		}

		~ComponentRefVectorOwning() {
			for (size_t i = 0; i < ComponentRefVector<T>::components.size(); i++)
			{
				ComponentRefVector<T>::components[i]->RemoveOwner();
			}
		}

		void AddComponent(T* component) override {
			ComponentRefVector<T>::AddComponent(component);
			component->AddOwner();

		}

		void RemoveComponent(T* component) override {
			ComponentRefVector<T>::RemoveComponent(component);
			component->RemoveOwner();
		}
	};
}