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


#include "SniperClass.h"
#include "EndlessVendetta/EndlessVendettaCharacter.h"
#include "EndlessVendetta/AI/AICharacter.h"
#include "Engine/DamageEvents.h"
#include "Kismet/GameplayStatics.h"

// Sets default values
ASniperClass::ASniperClass()
{
	// 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 ASniperClass::BeginPlay()
{
	Super::BeginPlay();
}

// Called every frame
void ASniperClass::Tick(float DeltaTime)
{
	ApplyRecoil(DeltaTime);
	recoilMagnitude = 1;
	if(endlessVendettaChar->bIsPlayerMoving == false )
	{
		recoilResultPitch = 0;
		recoilMagnitude = -1;
	}
	if (currentPitch < 0 && bStopShooting)
	{
		float increment = currentPitch * DeltaTime * 8;
		currentPitch -= increment;
		playerInWorld->AddControllerPitchInput(-increment);
	}
}

void ASniperClass::Fire()
{
	if(currentAmmoCount > 0 && !bSingleShotOnly)
	{
		bSingleShotOnly = true;
		//do damage fallof based off distance
		traceStart = GunStartArrow->GetComponentLocation();
		traceEnd = traceStart + (GunStartArrow->GetForwardVector() * BulletDistance);
		if (GetWorldTimerManager().IsTimerActive(timerHandle)) return;
		GetWorld()->LineTraceSingleByChannel(outHit, traceStart, traceEnd, ECC_Visibility, collisionParams);
		DrawDebugLine(this->GetWorld(), traceStart, traceEnd, FColor::Black , false, 0.2f, 0U, 0.2f);
		playerControllerRef->PlayerCameraManager->StartCameraShake(CameraShakeClass, 1);
		currentAmmoCount -= 1;
		bulletCountShoot += 1;
		bStopShooting = false;
		GenerateRecoilVector();
		ApplyRecoil(UGameplayStatics::GetWorldDeltaSeconds(this->GetWorld()));
		this->GetWorld()->GetTimerManager().SetTimer(SniperTimerHandle, this, &ASniperClass::StopFire, FireRate, false);
		if (outHit.bBlockingHit)
		{
			if (outHit.Distance >= FMath::Floor(BulletDistance/2))
			{
				tempWeaponDamage = WeaponDamage / 2;
			}
			else
			{
				tempWeaponDamage = WeaponDamage;
			}
			if (!Cast<AAICharacter>(outHit.GetActor())) return;
			Cast<AAICharacter>(outHit.GetActor())->TakeDamage(tempWeaponDamage, FPointDamageEvent(), GetWorld()->GetFirstPlayerController(), this);
		}
	}
	else if(currentAmmoCount <= 0)
	{
		UE_LOG(LogTemp, Display, TEXT("No ammo, Ammo count: %d"), currentAmmoCount);
	}
}

void ASniperClass::ApplyRecoil(float DeltaTime)
{
	if (recoilTime < 0.3)
	{
		float amplitude = RecoilCurve->GetFloatValue(recoilTime); //get current value of curve in time
		recoilTime += DeltaTime;
		
		playerInWorld->AddControllerPitchInput(GetRecoilPitch(amplitude, recoilTime));
		
		currentPitch += GetRecoilPitch(amplitude,recoilTime);
		
		playerInWorld->AddControllerPitchInput(FMath::RandRange(-5 * DeltaTime, 5* DeltaTime));
		GunStartArrow->AddRelativeRotation(FRotator(-GetRecoilPitch(amplitude, recoilTime), 0, 0));
		playerInWorld->AddControllerYawInput(GetRecoilYaw(amplitude, recoilTime));
		
		UpdateSamples(amplitude, recoilTime);
	}
}

void ASniperClass::StopFire()
{
	bSingleShotOnly = false;
}
