// Project Lab - NHTV Igad

#include "UnrealProject.h"
#include "CreatureSpawnComponent.h"
#include "SpawnerBase.h"
#include "GeneralEnemy.h"
#include "OffensiveEnemy.h"
#include "RangedEnemy.h"
#include "EnemyBase.h"

#define CONEARCVERTEXCOUNT 50

UCreatureSpawnComponent::UCreatureSpawnComponent(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
{
	ShapeColor = FColor(223, 149, 157, 255);
	spawnerBase = Cast<ASpawnerBase>(GetAttachmentRootActor());
	bUseEditorCompositing = true;
}

FPrimitiveSceneProxy* UCreatureSpawnComponent::CreateSceneProxy()
{
	class FDrawConeSceneProxy : public FPrimitiveSceneProxy
	{
	public:
		const UCreatureSpawnComponent* component;
		FDrawConeSceneProxy(const UCreatureSpawnComponent* InComponent)
			: FPrimitiveSceneProxy(InComponent)
			, spawnerBase(InComponent->spawnerBase)
			, bDrawOnlyIfSelected(InComponent->bDrawOnlyIfSelected)
			, component(InComponent)
		{
			bWillEverBeLit = false;
		}


		virtual void GetDynamicMeshElements(const TArray<const FSceneView*>& Views, const FSceneViewFamily& ViewFamily, uint32 VisibilityMap, FMeshElementCollector& Collector) const override
		{
			QUICK_SCOPE_CYCLE_COUNTER(STAT_GetDynamicMeshElements_DrawDynamicElements);

			const FMatrix& LocalToWorld = GetLocalToWorld();

			for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++)
			{
				const FSceneView* View = Views[ViewIndex];

				FPrimitiveDrawInterface* PDI = Collector.GetPDI(ViewIndex);
				if (spawnerBase)
				{

					FTransform transform = component->GetAttachParent()->GetComponentTransform();
					FVector base = transform.GetLocation();
					

					const float scale = 1.0f / 180.0f * PI;
					float baseRot = (360.0f - transform.GetRotation().Euler().Z) * scale;

					//FVector forward = FVector(1, 0, 0).RotateAngleAxis(0.0f, FVector(0, 0, 1));
					//FVector right = FVector(0, 1, 0).RotateAngleAxis(0.0f, FVector(0, 0, 1));
					FVector forward = FVector(1, 0, 0);
					FVector right = FVector(0, 1, 0);
					float angle = (360.0f) / 180.0f * PI;

					FVector linePoints[CONEARCVERTEXCOUNT];
					float anglestep = (angle) / (CONEARCVERTEXCOUNT - 1);

					float rot = baseRot - angle * 0.5f;
					for (int i = 0; i < CONEARCVERTEXCOUNT; i++)
					{
						float f = cosf(rot);
						float r = sinf(rot);
						linePoints[i] = base + (forward * f - right * r) * spawnerBase->aggroRadius;
						rot += anglestep;
					}

					for (int i = 0; i < CONEARCVERTEXCOUNT - 1; i++)
					{

						PDI->DrawLine(linePoints[i], linePoints[i + 1], ShapeColor, SDPG_World);
					}
					for (int i = 0; i < CONEARCVERTEXCOUNT; i++)
					{
						float f = cosf(rot);
						float r = sinf(rot);
						linePoints[i] = base + (forward * f - right * r) * spawnerBase->deaggroRadius;
						rot += anglestep;
					}

					for (int i = 0; i < CONEARCVERTEXCOUNT - 1; i++)
					{

						PDI->DrawLine(linePoints[i], linePoints[i + 1], FColor(0,0,255), SDPG_World);
					}
					FVector last = spawnerBase->GetActorLocation();
					FVector first;
					for (int32 i = 0; i < spawnerBase->controlPoints.Num(); i++)
					{
						
 						FTransform transform = component->GetAttachParent()->GetComponentTransform();
						FVector base = transform.GetLocation() + FVector(spawnerBase->controlPoints[i].X, spawnerBase->controlPoints[i].Y, 0);
						if (i == 0)
							first = base;
					
						const float scale = 1.0f / 180.0f * PI;
						float baseRot = (360.0f - transform.GetRotation().Euler().Z) * scale;

						//FVector forward = FVector(1, 0, 0).RotateAngleAxis(0.0f, FVector(0, 0, 1));
						//FVector right = FVector(0, 1, 0).RotateAngleAxis(0.0f, FVector(0, 0, 1));
						FVector forward = FVector(1, 0, 0);
						FVector right = FVector(0, 1, 0);
						float angle = (360.0f) / 180.0f * PI;

						FVector linePoints[CONEARCVERTEXCOUNT];
						float anglestep = (angle) / (CONEARCVERTEXCOUNT - 1);

						float rot = baseRot - angle * 0.5f;
						for (int i = 0; i < CONEARCVERTEXCOUNT; i++)
						{
							float f = cosf(rot);
							float r = sinf(rot);
							linePoints[i] = base + (forward * f - right * r) * spawnerBase->drawingRadius;
							rot += anglestep;
						}

						for (int i = 0; i < CONEARCVERTEXCOUNT - 1; i++)
						{

							PDI->DrawLine(linePoints[i], linePoints[i + 1], ShapeColor, SDPG_World);
						}
						PDI->DrawLine(base, last, ShapeColor, SDPG_World);
						last = base;
						//PDI->DrawLine(base, linePoints[CONEARCVERTEXCOUNT - 1], ShapeColor, SDPG_World);
					}
					if (spawnerBase->isConnected)
						PDI->DrawLine(first, last, ShapeColor, SDPG_World);
					for (int32 i = 0; i < spawnerBase->formationPoints.Num(); i++)
					{
						FColor formationColor = FColor(100, 100, 100);
						//AEnemyBase *creature = (dynamic_cast<AGeneralEnemy*>(spawnerBase->spawns[i]));
						FTransform transform = component->GetAttachParent()->GetComponentTransform();
						FVector base = transform.GetLocation() + spawnerBase->GetActorRotation().RotateVector( FVector(spawnerBase->formationPoints[i].X, spawnerBase->formationPoints[i].Y, 0))*spawnerBase->formationScale;
						if (i == 0)
							first = base;

						const float scale = 1.0f / 180.0f * PI;
						float baseRot = (360.0f - transform.GetRotation().Euler().Z) * scale;

						//FVector forward = FVector(1, 0, 0).RotateAngleAxis(0.0f, FVector(0, 0, 1));
						//FVector right = FVector(0, 1, 0).RotateAngleAxis(0.0f, FVector(0, 0, 1));
						FVector forward = FVector(1, 0, 0);
						FVector right = FVector(0, 1, 0);
						float angle = (360.0f) / 180.0f * PI;

						FVector linePoints[CONEARCVERTEXCOUNT];
						float anglestep = (angle) / (CONEARCVERTEXCOUNT - 1);

						float rot = baseRot - angle * 0.5f;
						for (int j = 0; j < CONEARCVERTEXCOUNT; j++)
						{
							float f = cosf(rot);
							float r = sinf(rot);
							linePoints[j] = base + (forward * f - right * r) * spawnerBase->drawingRadius;
							rot += anglestep;
						}
						if (i >= spawnerBase->spawns.Num())
						{
							formationColor.B = 10;
							formationColor.G = 10;
							formationColor.R = 10;

						}
						else
						{
						
							if ((spawnerBase->spawns[i])->IsChildOf(AGeneralEnemy::StaticClass()))
							{
								formationColor.B = 255;
								formationColor.G = 255;
								formationColor.R = 255;
							}
							else
							{
								formationColor.B = 42;
								formationColor.G = 42;
								formationColor.R = 42;
							}
							if ((spawnerBase->spawns[i])->IsChildOf(ARangedEnemy::StaticClass())&& !spawnerBase->spawns[i]->IsChildOf(AGeneralEnemy::StaticClass()))
							{
								formationColor.B = 0;
								formationColor.G = 255;
								formationColor.R = 0;
							}
							
							if ((spawnerBase->spawns[i])->IsChildOf(AOffensiveEnemy::StaticClass()))
							{
								formationColor.B = 0;
								formationColor.G = 0;
								formationColor.R = 255;
							}
						
						}
						for (int j = 0; j < CONEARCVERTEXCOUNT - 1; j++)
						{

							PDI->DrawLine(linePoints[j], linePoints[j + 1], formationColor, SDPG_World);
						}
						if (i < spawnerBase->formationRotation.Num())
						{
						
						PDI->DrawLine(base, base+(FRotator(0, spawnerBase->formationRotation[i],0).RotateVector( spawnerBase->GetActorForwardVector())* spawnerBase->drawingRadius), formationColor, SDPG_World);
						}
						else PDI->DrawLine(base, base + (spawnerBase->GetActorForwardVector())* spawnerBase->drawingRadius, formationColor, SDPG_World);
					//	PDI->DrawLine(base, last, formationColor, SDPG_World);
						last = base;
						//PDI->DrawLine(base, linePoints[CONEARCVERTEXCOUNT - 1], ShapeColor, SDPG_World);
					}
					//if (spawnerBase->isConnected)
					//	PDI->DrawLine(first, last, ShapeColor, SDPG_World);
				
				}
			}
		}

		virtual FPrimitiveViewRelevance GetViewRelevance(const FSceneView* View) const override
		{
			FPrimitiveViewRelevance Result;
			Result.bDrawRelevance = IsSelected();
			Result.bDynamicRelevance = true;
			Result.bShadowRelevance = IsShadowCast(View);
			Result.bEditorPrimitiveRelevance = UseEditorCompositing(View);
			return Result;
		}

		virtual uint32 GetMemoryFootprint(void) const override { return(sizeof(*this) + GetAllocatedSize()); }
		uint32 GetAllocatedSize(void) const { return(FPrimitiveSceneProxy::GetAllocatedSize()); }

	private:
		const uint32	bDrawOnlyIfSelected : 1;
		const ASpawnerBase* spawnerBase;
		const FColor	ShapeColor = FColor(255, 0, 0, 255);
		const FTransform transform;
	};

	return new FDrawConeSceneProxy(this);
}