// Fill out your copyright notice in the Description page of Project Settings.


#include "VisionLink.h"

#include "CollisionDebugDrawingPublic.h"
#include "Kismet/KismetMathLibrary.h"
#include "Camera/CameraComponent.h"
#include "EndlessVendetta/EndlessVendettaCharacter.h"
#include "GameFramework/Character.h"

void AVisionLink::BeginPlay()
{
	Super::BeginPlay();
	SetActorTickEnabled(false);
	CooldownLength = CooldownTime;
	InUseDuration = GadgetMaxUptime;

	if (NumberOfPingPulses <= 0) NumberOfPingPulses = 1;
	TimeInbetweenPingPulses = GadgetMaxUptime / (float)NumberOfPingPulses;
}

void AVisionLink::Activate()
{
	if (GadgetCantBeUsed()) return;

	Super::Activate();

	NumOfPingPulsesLeftInThisCycle = NumberOfPingPulses;
	VisionLinkActivated();
	SendOutPingPulse();
}

void AVisionLink::FinishedUsing()
{
	VisionLinkRecharging();

	Super::FinishedUsing();
}

void AVisionLink::SendOutPingPulse()
{
	NumOfPingPulsesLeftInThisCycle--;
	UpdatePulsesRemaining(NumOfPingPulsesLeftInThisCycle);
	if (NumOfPingPulsesLeftInThisCycle < 0) return;
	
	GetWorld()->GetTimerManager().SetTimer(PulseHandle, this, &AVisionLink::SendOutPingPulse, TimeInbetweenPingPulses, false);
	PlayPingPulseAnim(TimeInbetweenPingPulses);

	ACharacter* PlayersCharacter = GetWorld()->GetFirstPlayerController()->GetCharacter();
	UCameraComponent* PlayerCamComp = Cast<UCameraComponent>(PlayersCharacter->GetComponentByClass(UCameraComponent::StaticClass()));

	// Ignored Actors
	TArray<AActor*> ActorsToIgnore;
	AEndlessVendettaCharacter* EV_Character = Cast<AEndlessVendettaCharacter>(PlayersCharacter);
	if ( IsValid(EV_Character) && IsValid(EV_Character->PrimaryWeaponActor)) ActorsToIgnore.Add(EV_Character->PrimaryWeaponActor);
	if ( IsValid(EV_Character) && IsValid(EV_Character->SecondaryWeaponActor)) ActorsToIgnore.Add(EV_Character->SecondaryWeaponActor);
	ActorsToIgnore.Add(PlayersCharacter);

	TestLOS(PlayerCamComp->GetComponentTransform(), ActorsToIgnore);
}

void AVisionLink::TestLOS(FTransform StartingPos, TArray<AActor*> &ActorsToIgnore)
{
	float H_DegreeIncrement = (float)H_FOV / (float)LT_Horizontal_Density;
	float V_DegreeIncrement = (float)V_FOV / (float)LT_Vertical_Density;
	float H_StartingRot = StartingPos.GetRotation().Rotator().Yaw - ((float)H_FOV / 2.0);
	float V_StartingRot = StartingPos.GetRotation().Rotator().Pitch - ((float)V_FOV / 2.0);

	for (int H_Increment = 1; H_Increment <= LT_Horizontal_Density; H_Increment++)
	{
		for (int V_Increment = 1; V_Increment <= LT_Vertical_Density; V_Increment++)
		{
			FHitResult outHit;
			FCollisionQueryParams QueryParams = FCollisionQueryParams::DefaultQueryParam;
			QueryParams.bTraceComplex = true;
			QueryParams.AddIgnoredActors(ActorsToIgnore);
			
			FRotator LT_Rot = FRotator(V_StartingRot + (V_Increment * V_DegreeIncrement), H_StartingRot + (H_Increment * H_DegreeIncrement), StartingPos.GetRotation().Rotator().Roll);
			FVector LT_EndPoint = StartingPos.GetLocation() + UKismetMathLibrary::GetForwardVector(LT_Rot) * LT_Distance;
			
			if (!GetWorld()->LineTraceSingleByChannel(outHit, StartingPos.GetLocation(), LT_EndPoint, ECC_Camera, QueryParams)) continue;
			
			AActor* HitActor = outHit.GetActor();
			if (!HitActor->ActorHasTag(FName("Enemy")) || HitActor->ActorHasTag("Dead")) continue;

			//DrawDebugLine(GetWorld(), outHit.TraceStart, outHit.ImpactPoint, FColor::Blue, false, 3, 0, 3);	
			ActorsToIgnore.Add(HitActor);
			SpawnPing(HitActor->GetTransform());
			TestLOS(HitActor->GetTransform(), ActorsToIgnore);
		}
	}
}

