// Project Lab - NHTV Igad

#include "UnrealProject.h"
#include "EnemyAIController.h"
#include "EnemyBase.h"
#include "NetworkCharacter.h"
#include "Navigation/CrowdFollowingComponent.h"

#include "BehaviorTree/BehaviorTree.h"
#include "BehaviorTree/BlackboardComponent.h"

#include "BehaviorTree/BehaviorTreeComponent.h"
#include "BehaviorTree/BlackBoard/BlackboardKeyAllTypes.h"

#include "DrawDebugHelpers.h"

AEnemyAIController::AEnemyAIController(const FObjectInitializer& PCIP)
	//: Super(PCIP.SetDefaultSubobjectClass<UCrowdFollowingComponent>(TEXT("PathFollowingComponent")))
{
	blackBoardComp = CreateDefaultSubobject<UBlackboardComponent>(FName("BlackBoardComp"));
	behaviorTreeComp = CreateDefaultSubobject<UBehaviorTreeComponent>(FName("BehaviorTreeComp"));
	climbSpeed = 1.0f;
}
void AEnemyAIController::Tick(float deltaTime)
{
	Super::Tick(deltaTime);

}
void AEnemyAIController::Possess(APawn* pawn)
{
	Super::Possess(pawn);
	AEnemyBase* enemy = Cast<AEnemyBase>(pawn);
	if (enemy &&enemy->treeBehavior)
	{
		if (!enemy->treeBehavior->BlackboardAsset)
		{
			RERROR("There is no blackboard asset in the behavior tree");
			return;
		}
		blackBoardComp->InitializeBlackboard(*(enemy->treeBehavior->BlackboardAsset));
		behaviorTreeComp->StartTree(*enemy->treeBehavior);
	}
}
bool AEnemyAIController::VerticleMoveTo(FVector destination, FVector direction,float acceptRadius)
{
	FVector location =GetPawn()->GetActorLocation();
	FVector dest = destination;
	dest -= location;

	dest *= direction;
	FVector newDest= dest;
	float height = newDest.Size();



	if (height < acceptRadius&&destination.Z <location.Z)
	{
	//	GetCharacter()->GetCharacterMovement()->GravityScale = 1;

		return true;
	}

	GetPawn()->SetActorLocation(FVector(location.X+(direction.X*10), location.Y+(direction.Y*10) , (location.Z)+(direction.Z*10)));
	GetCharacter()->GetCharacterMovement()->GravityScale = 0;
	
	return false;

}
bool AEnemyAIController::JumpFence(FVector destination)
{
	TArray<FHitResult> result;
	UNavigationSystem* navsys = UNavigationSystem::GetCurrent(GetWorld());
	if (!navsys)
	{
		RERROR("There is no navigation system in the current level, please check if there is one or contact a developer!");
		return false;
	}
	ANPCBase* character = Cast<ANPCBase>(GetPawn());
	FVector direction;
	FNavLocation navLocation;
	character->SetActorEnableCollision(false);
	DrawDebugLine(GetWorld(), GetPawn()->GetActorLocation(), GetPawn()->GetActorLocation() + GetActorUpVector()*-10000.0f, 	FColor(255, 0, 0),false, -1, 0,	12.333);
	FCollisionQueryParams collisionParams;
	collisionParams.AddIgnoredActor(this->GetPawn());
	GetWorld()->LineTraceMultiByChannel(result, GetPawn()->GetActorLocation(), GetPawn()->GetActorLocation() + GetActorUpVector()*-10000.0f, ECollisionChannel::ECC_WorldStatic, collisionParams);
	for (int i = 0; i < result.Num(); i++)
	{

		if(result[i].ImpactPoint!=GetPawn()->GetActorLocation())
		{
			if (!navsys->ProjectPointToNavigation(GetPawn()->GetActorLocation(),  navLocation))
			{
				continue;
			}
			GetCharacter()->GetCharacterMovement()->GravityScale = 1;
			SetBool(false,FName("ClimbKey"));
			navsys->SimpleMoveToLocation(this,destination);
			character->PlayNormalAnimation();
			character->SetActorEnableCollision(true);
			return true;
		}
	}
	character->PlayFencAnimation();
	direction = destination - GetPawn()->GetActorLocation();
	direction.Normalize();
	GetPawn()->SetActorLocation(GetPawn()->GetActorLocation()+(direction * 10));
	return false;
}
void AEnemyAIController::BeginInactiveState()
{
	Super::BeginInactiveState();
}
void AEnemyAIController::SetVector(FVector vector, FName name)
{
	if (blackBoardComp)
	{
		blackBoardComp->SetValueAsVector(name, (vector));
	}

}
void AEnemyAIController::SetBool(bool boolean, FName name)
{
	if (blackBoardComp)
	{
		blackBoardComp->SetValueAsBool(name, (boolean));
	}

}
void AEnemyAIController::SetTarget(ANetworkCharacter* player)
{
	if (blackBoardComp)
	{
		blackBoardComp->SetValueAsObject((FName("Target")), (player));
	}
}
ANetworkCharacter* AEnemyAIController::GetTarget()
{
	if (blackBoardComp)
	{
		return Cast<ANetworkCharacter>(blackBoardComp->GetValue<UBlackboardKeyType_Object>(FName("Target")));
	}
	return nullptr;

}

FVector AEnemyAIController::GetLocationTarget()
{
	if (blackBoardComp)
	{
		return FVector(blackBoardComp->GetValue<UBlackboardKeyType_Vector>(FName("TargetLocation")));
	}
	return FVector();
}

FVector AEnemyAIController::GetHomeLocation()
{
	if (blackBoardComp)
	{
		return FVector(blackBoardComp->GetValue<UBlackboardKeyType_Vector>(FName("HomeLocation")));
	}
	return FVector();
}
FVector AEnemyAIController::GetSelfLocation()
{
	if (blackBoardComp)
	{
		return FVector(blackBoardComp->GetValue<UBlackboardKeyType_Vector>(FName("SelfLocation")));
	}
	return FVector();
}
bool AEnemyAIController::GetClimbKey()
{
	if (blackBoardComp)
	{
		return  blackBoardComp->GetValue<UBlackboardKeyType_Bool>((FName("ClimbKey")));
	}
	else return false;
}