// Project Lab - NHTV Igad

#include "UnrealProject.h"
#include "DefaultGameInstance.h"
#include "Prefs.h"
#include "ItemBase.h"
#include "Effect.h"
#include "AbilityIndicator.h"
#include "NetworkCharacter.h"
#include "NetworkPlayer.h"
#include "EffectFunctionLibrary.h"

AEffect* UEffectFunctionLibrary::CreateEffect(UObject* worldContextObject, TSubclassOf<class AEffect> effectClass, 
	class AActor* followObject, float startTime, float durationOverride, bool clientSideOnly)
{
	UWorld* world = GEngine->GetWorldFromContextObject(worldContextObject);
	if(!effectClass)
	{
		GWERROR(L"Can't create effect, class not set");
		return nullptr;
	}
	if(!world)
	{
		GWERROR(L"Can't create effect, world not set");
		return nullptr;
	}
	if(!world->GetAuthGameMode())
		return nullptr; // Only server can spawn replicated effects

	FTransform spawnTransform = FTransform::Identity;
	if(followObject)
	{
		spawnTransform = followObject->GetTransform();
	}

	else
	{
		AActor* spawnActor = Cast<AActor>(worldContextObject);
		if(spawnActor)
			spawnTransform = spawnActor->GetTransform();
	}

	spawnTransform.SetScale3D(FVector(1.0f, 1.0f, 1.0f)); // Reset scale, only inherit parent position + rotation

	AEffect* pfx = world->SpawnActorDeferred<AEffect>(effectClass, spawnTransform);
	if(!pfx)
		return nullptr;
	pfx->m_lifeTime = startTime;
	pfx->Init(durationOverride, followObject, clientSideOnly);
	UGameplayStatics::FinishSpawningActor(pfx, spawnTransform);
	return pfx;
}


	AEffect* UEffectFunctionLibrary::CreateEffectAt(UObject* worldContextObject, TSubclassOf<class AEffect> effectClass,
		const FTransform& transform, float startTime, float durationOverride, bool clientSideOnly)
	{
		UWorld* world = GEngine->GetWorldFromContextObject(worldContextObject);
		if (!effectClass)
		{
			GWERROR(L"Can't create effect, class not set");
			return nullptr;
		}
		if (!world)
		{
			GWERROR(L"Can't create effect, world not set");
			return nullptr;
		}
		if (!world->GetAuthGameMode())
			return nullptr; // Only server can spawn replicated effects
		AEffect* pfx = world->SpawnActorDeferred<AEffect>(effectClass, transform);
		check(pfx);
		pfx->m_lifeTime = startTime;
		pfx->Init(durationOverride, nullptr, clientSideOnly);

		UGameplayStatics::FinishSpawningActor(pfx, transform);
		return pfx;
	}

	AEffect* UEffectFunctionLibrary::CreateEffectAttached(UObject* worldContextObject, TSubclassOf<class AEffect> effectClass,
		const FTransform& transform, USceneComponent* InParent, FName InSocketName, EAttachLocation::Type AttachLocationType, float startTime, float durationOverride, bool clientSideOnly)
	{
		UWorld* world = GEngine->GetWorldFromContextObject(worldContextObject);
		if (!effectClass)
		{
			GWERROR(L"Can't create effect, class not set");
			return nullptr;
		}
		if (!world)
		{
			GWERROR(L"Can't create effect, world not set");
			return nullptr;
		}
		if (!world->GetAuthGameMode())
			return nullptr; // Only server can spawn replicated effects
		AEffect* pfx = world->SpawnActorDeferred<AEffect>(effectClass, transform);
		check(pfx);
		pfx->m_lifeTime = startTime;
		pfx->Init(durationOverride, nullptr, clientSideOnly);
		UGameplayStatics::FinishSpawningActor(pfx, transform);
		pfx->AttachRootComponentTo(InParent, InSocketName, AttachLocationType);
		return pfx;
	}

AAbilityIndicator * UEffectFunctionLibrary::CreateAbilityIndicator(TSubclassOf<class AAbilityIndicator> AAbilityIndicatorClass, ANetworkCharacter* spawner, AActor* followObject, FVector scale, float durationOverride, bool center)
{
	if (!spawner)
	{
		FWERROR(L"Can't create abilityIndicator, spawner not set");
		return nullptr;
	}
	//transforming from cm to m duo to 4.11
	FVector newscale = scale * 0.01f; 
	UWorld* world = spawner->GetWorld();
	FTransform spawnTransform = spawner->GetTransform();
	AAbilityIndicator* pai = world->SpawnActorDeferred<AAbilityIndicator>(AAbilityIndicatorClass, spawnTransform);
	check(pai);
	if (center)
		pai->Init(durationOverride, FVector(0, 0.0, 0), FRotator(0, 90, 0), newscale * 0.5f, center, followObject, pai->teamData->GetTeamColor(spawner->GetTeam()));
	else
		pai->Init(durationOverride, FVector(0, scale.Y, 0) + FVector(0,100,0), FRotator(0, 90, 0), newscale * 0.5f, center, followObject, pai->teamData->GetTeamColor(spawner->GetTeam()));
	UGameplayStatics::FinishSpawningActor(pai, spawnTransform);
	return pai;
}

AAbilityIndicator * UEffectFunctionLibrary::CreateAbilityIndicatorAt(TSubclassOf<class AAbilityIndicator> AAbilityIndicatorClass, ANetworkCharacter * spawner, const FTransform& transform, FVector scale, float durationOverride, bool center)
{
	if (!spawner)
	{
		FWERROR(L"Can't create abilityIndicator, spawner not set");
		return nullptr;
	}
	FVector newscale = scale * 0.01f;
	UWorld* world = spawner->GetWorld();
	FTransform spawnTransform = transform;
	AAbilityIndicator* pai = world->SpawnActorDeferred<AAbilityIndicator>(AAbilityIndicatorClass, spawnTransform);
	check(pai);
	if (center)
		pai->Init(durationOverride, FVector(0, 0.0, 0), FRotator(0, 90, 0), newscale * 0.5f, center, nullptr, pai->teamData->GetTeamColor(spawner->GetTeam()));
	else
		pai->Init(durationOverride, FVector(0, scale.Y * 0.5f, 0), FRotator(0, 90, 0), newscale * 0.5f, center, nullptr, pai->teamData->GetTeamColor(spawner->GetTeam()));
	UGameplayStatics::FinishSpawningActor(pai, spawnTransform);
	return pai;
}

void UEffectFunctionLibrary::PlaySoundEffect2D(UObject* worldContextObject, USoundBase* sound)
{
	UWorld* world = GEngine->GetWorldFromContextObject(worldContextObject);
	float volume = Cast<UDefaultGameInstance>(world->GetGameInstance())->GetPrefs()->sfxVolume;
	UGameplayStatics::PlaySound2D(worldContextObject, sound, volume);
}

void UEffectFunctionLibrary::DuplicateAppearance(ACharacterBase* from, ACharacterBase* to)
{
	if (from == nullptr)
	{
		FWARNING("from == nullptr");
		return;
	}
	USkeletalMeshComponent* fromMesh = from->GetMesh();
	if (fromMesh == nullptr)
	{
		FWARNING("from->mesh == nullptr");
		return;
	}
	if (to == nullptr)
	{
		FWARNING("to == nullptr");
		return;
	}
	// Copy equiped items
	TArray<TSubclassOf<AItemBase>> itemsToSpawn;
	for(auto i : from->GetEquipedItems())
	{
		itemsToSpawn.Add(i->GetClass());
	}
	to->EquipItems(itemsToSpawn);

	// Copy CUstomization
	to->SetCustomizations(from->GetCharacterCustomization());

	to->playerName = from->playerName;

	return;
}