#pragma once

#include "UtlVector.hpp"
#include "../Interfaces/IClientEntity.hpp"

class CGlowObjectManager {
public:

	int RegisterGlowObject(entity_t* pEntity, const Vector& vGlowColor, float flGlowAlpha, bool bRenderWhenOccluded, bool bRenderWhenUnoccluded, int nSplitScreenSlot) {
		int nIndex;
		if (m_nFirstFreeSlot == GlowObjectDefinition_t::END_OF_FREE_LIST) {
			nIndex = m_GlowObjectDefinitions.AddToTail();
		}
		else {
			nIndex = m_nFirstFreeSlot;
			m_nFirstFreeSlot = m_GlowObjectDefinitions[nIndex].m_nNextFreeSlot;
		}

		m_GlowObjectDefinitions[nIndex].m_hEntity = pEntity;
		m_GlowObjectDefinitions[nIndex].m_vGlowColor = vGlowColor;
		m_GlowObjectDefinitions[nIndex].m_flGlowAlpha = flGlowAlpha;
		//m_GlowObjectDefinitions[nIndex].flUnk = 0.0f;
		m_GlowObjectDefinitions[nIndex].m_flBloomAmount = 1.0f;
		//m_GlowObjectDefinitions[nIndex].localplayeriszeropoint3 = 0.0f;
		m_GlowObjectDefinitions[nIndex].m_bRenderWhenOccluded = bRenderWhenOccluded;
		m_GlowObjectDefinitions[nIndex].m_bRenderWhenUnoccluded = bRenderWhenUnoccluded;
		m_GlowObjectDefinitions[nIndex].m_bFullBloomRender = false;
		//m_GlowObjectDefinitions[nIndex].m_nFullBloomStencilTestValue = 0;
		m_GlowObjectDefinitions[nIndex].m_nSplitScreenSlot = nSplitScreenSlot;
		m_GlowObjectDefinitions[nIndex].m_nNextFreeSlot = GlowObjectDefinition_t::ENTRY_IN_USE;

		return nIndex;
	}

	void UnregisterGlowObject(int nGlowObjectHandle) {
		Assert(!m_GlowObjectDefinitions[nGlowObjectHandle].IsUnused());

		m_GlowObjectDefinitions[nGlowObjectHandle].m_nNextFreeSlot = m_nFirstFreeSlot;
		m_GlowObjectDefinitions[nGlowObjectHandle].m_hEntity = NULL;
		m_nFirstFreeSlot = nGlowObjectHandle;
	}

	int HasGlowEffect(entity_t* pEntity) const { //-V2009
		for (int i = 0; i < m_GlowObjectDefinitions.Count(); ++i) {
			if (!m_GlowObjectDefinitions[i].IsUnused() && m_GlowObjectDefinitions[i].m_hEntity == pEntity) {
				return i;
			}
		}

		return NULL;
	}

	class GlowObjectDefinition_t {
	public:
		void Set(float r, float g, float b, float a, float bloom, int style) {
			m_vGlowColor = Vector(r, g, b);
			m_flGlowAlpha = a;
			m_bRenderWhenOccluded = true;
			m_bRenderWhenUnoccluded = false;
			m_flBloomAmount = bloom;
			m_nGlowStyle = style;
		}

		entity_t* GetEnt() {
			return m_hEntity;
		}

		bool IsUnused() const { return m_nNextFreeSlot != GlowObjectDefinition_t::ENTRY_IN_USE; }

	public:
		int m_nNextFreeSlot;
		entity_t* m_hEntity;

		Vector m_vGlowColor;
		float m_flGlowAlpha;

		bool m_bGlowAlphaCappedByRenderAlpha;
		float m_flGlowAlphaFunctionOfMaxVelocity;

		float m_flGlowAlphaMax;
		float m_flGlowPulseOverdrive;

		bool m_bRenderWhenOccluded;
		bool m_bRenderWhenUnoccluded;
		bool m_bFullBloomRender;
		int m_flBloomAmount; // m_nFullBloomStencilTestValue ?

		int m_nGlowStyle;
		int m_nSplitScreenSlot;

		static const int END_OF_FREE_LIST = -1;
		static const int ENTRY_IN_USE = -2;
	};

	CUtlVector< GlowObjectDefinition_t > m_GlowObjectDefinitions;
	int m_nFirstFreeSlot;

};

/*
int m_nNextFreeSlot;
C_BaseEntity* m_pEntity;
Vector m_vGlowColor;
float m_flGlowAlpha;
bool m_bGlowAlphaCappedByRenderAlpha;
float m_flGlowAlphaFunctionOfMaxVelocity;
float m_flGlowAlphaMax;
float m_flGlowPulseOverdrive;
bool m_bRenderWhenOccluded;
bool m_bRenderWhenUnoccluded;
bool m_bFullBloomRender;
int m_nFullBloomStencilTestValue;
int m_nRenderStyle;
int m_nSplitScreenSlot;
*/