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


#include "Explosive.h"

#include "CollisionDebugDrawingPublic.h"
#include "Kismet/KismetMathLibrary.h"
#include "Engine/DamageEvents.h"
#include "EndlessVendetta/AI/AICharacter.h"

// Sets default values
AExplosive::AExplosive()
{
 	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

}

// Called when the game starts or when spawned
void AExplosive::BeginPlay()
{
	Super::BeginPlay();

	if (ExplosionDelayInSeconds <= 0)
	{
		Explosion();
		return;
	}

	FTimerHandle ExplosionHandle;
	GetWorld()->GetTimerManager().SetTimer(ExplosionHandle, this, &AExplosive::Explosion, ExplosionDelayInSeconds);
}

// Called every frame
void AExplosive::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

void AExplosive::Explosion()
{
	float PitchAngleIncrement = 180.f / ShrapnelPitchDensity;
	float YawAngleIncrement = 360.f / ShrapnelYawDensity;
	
	FHitResult OutHit;
	FCollisionQueryParams QueryParams = FCollisionQueryParams::DefaultQueryParam;
	QueryParams.bTraceComplex = false;
	QueryParams.AddIgnoredActor(this);
	FVector LT_Start = GetActorLocation();
	
	for(int y = 1; y <= ShrapnelPitchDensity; y++)
	{
		for (int x = 1; x <= ShrapnelYawDensity; x++)
		{
			FRotator ShrapnelRotation = FRotator(-90.f + (y * PitchAngleIncrement), x * YawAngleIncrement, 0.f);
			FVector LT_End = LT_Start + (UKismetMathLibrary::GetForwardVector(ShrapnelRotation) * ShrapnelTravelDistance);
			bool HitSomething = GetWorld()->LineTraceSingleByChannel(OutHit, LT_Start, LT_End, ECC_Camera, QueryParams);

			if (DrawDebugLines)	DrawShrapnelDebugLines(HitSomething, LT_Start, LT_End, OutHit.ImpactPoint);
			if (!HitSomething || !OutHit.GetActor()->ActorHasTag(FName("Enemy")) || OutHit.GetActor()->ActorHasTag(FName("Dead"))) continue;

			float HitDistance = FVector::Distance(LT_Start, OutHit.ImpactPoint);
			float DamageToApply = ShrapnelDamage;
			if (HitDistance > ShrapnelDamageFalloffDistance)
			{
				// Damage linearly decrease from falloff distance to maximum travel distance, using straight line equation y = mx + c
				float Magnitude = ShrapnelDamage / (ShrapnelDamageFalloffDistance - ShrapnelTravelDistance);
				float DMG_Intercept = ShrapnelDamage - (Magnitude * ShrapnelDamageFalloffDistance);
				DamageToApply = (Magnitude * HitDistance) + DMG_Intercept;
			}
			// When merged, call philips take damage function here
			UE_LOG(LogTemp, Warning, TEXT("A shrapnel piece hit %s, dealing %f damage"), *OutHit.GetActor()->GetName(), DamageToApply);
			Cast<AAICharacter>(OutHit.GetActor())->TakeDamage(DamageToApply, FPointDamageEvent(), GetWorld()->GetFirstPlayerController(), this);
		}
	}
	PlayExplosionEffects();
}

void AExplosive::DrawShrapnelDebugLines(bool HitSomething, FVector StartVector, FVector EndVector, FVector ImpactPoint)
{
	if (!HitSomething)
	{
		DrawDebugLine(GetWorld(), StartVector, EndVector, FColor::Green, false, 5, 0, 2);
		return;
	}
	DrawDebugLine(GetWorld(), ImpactPoint, EndVector, FColor::Red, false, 5, 0, 2);
	DrawDebugLine(GetWorld(), StartVector, ImpactPoint, FColor::Green, false, 5, 0, 2);
}

