// Project Sword & Gun Copyright © 2021 Kevin Poretti


#include "Weapons/SNGMeleeWeaponBase.h"


#include "Characters/SNGCharacterBase.h"
#include "Kismet/KismetSystemLibrary.h"
#include "SwordNGun/SwordNGun.h"

ASNGMeleeWeaponBase::ASNGMeleeWeaponBase()
{
	GripName = "Grip";
	TipName = "Tip";

	AlreadyHitActors.Add(GetOwner());
}

void ASNGMeleeWeaponBase::ClearAlreadyHitActors()
{
	AlreadyHitActors.Empty();
	AlreadyHitActors.Add(GetOwner());
}

void ASNGMeleeWeaponBase::DoSphereCast(FSNGHitData const& HitData, bool OverrideStartAndEnd, FVector StartOverride, FVector EndOverride)
{
	if(!WeaponMesh)
	{
		UE_LOG(LogTemp, Error, TEXT("SNGMeleeWeaponBase :: Weapon has no mesh set"));
		return;
	}

	FTransform OwnerTransform = GetOwner()->ActorToWorld();
	FVector StartOverrideWorld = OwnerTransform.TransformPosition(StartOverride);
	FVector EndOverrideWorld = OwnerTransform.TransformPosition(EndOverride);
	
	FVector TraceStart = OverrideStartAndEnd ? StartOverrideWorld : WeaponMesh->GetSocketLocation(GripName);
	FVector TraceEnd = OverrideStartAndEnd ? EndOverrideWorld : WeaponMesh->GetSocketLocation(TipName);

	// get owner's type and ignore actors of that type
	// alternatively get a tag (e.g. "Players") and ignore all of them if you don't want friendly fire
	//TArray<AActor*> IgnoredActors;
	//IgnoredActors.Add(GetOwner());
	
	FHitResult HitResult;
	ETraceTypeQuery TraceType = UEngineTypes::ConvertToTraceType(COLLISION_WEAPON);
	if(UKismetSystemLibrary::SphereTraceSingle(this, TraceStart, TraceEnd, HitData.TraceRadius, TraceType, true,
		AlreadyHitActors, EDrawDebugTrace::Type::ForDuration, HitResult, true,
		FLinearColor::Green, FLinearColor::Red, 1.0f))
	{
		AActor* HitActor = HitResult.Actor.Get();
		AlreadyHitActors.Add(HitActor);
		
		FSNGDamageEvent DamageEvent;
		DamageEvent.DamageTypeClass = DamageType;
		DamageEvent.HitData = HitData;
		DamageEvent.SurfaceType = SurfaceType_Default;		
		HitActor->TakeDamage(HitData.Damage, DamageEvent,
			GetOwner()->GetInstigatorController(), this);

		if(HitData.HistopApplicationType == ESNGHitstopApplicationType::BOTH ||
			HitData.HistopApplicationType == ESNGHitstopApplicationType::ATTACKER_ONLY)
		{
			ASNGCharacterBase* OwnerAsChar = Cast<ASNGCharacterBase>(GetOwner());
			OwnerAsChar->ApplyHitStop(HitData.StopTime, HitData.SlowTime);
		}
		// NOTE(kevin): Want to rethink this calculate weapon damage thing. Is that needed in the melee weapon class?
		// I can't think of a scenario where you would want to do anything but set the damage as whatever value is in
		// the hit data that gets passed to this function. Need to think about this...
		/*
		HitActor->TakeDamage(CalculateWeaponDamage(), DamageEvent,
		GetOwner()->GetInstigatorController(), this);
		*/
	}
}
