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

#include "ld35.h"
#include "UcustomAnimInstance.h"
#include "Enemy.h"
#include "mainCharacter.h"


// Sets default values
AEnemy::AEnemy()
{
 	// Set this character to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;
	player = nullptr;
	hitForce = 0.0f;

}

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

	humanMesh		= (USkeletalMeshComponent *)	GetComponentByName("Human");
	
	if(humanMesh)	animationInstance = Cast<UcustomAnimInstance>( humanMesh->GetAnimInstance() );

	characterRotation	= 0.0f;
	actionTimer			= 0.0f;
	actionTimeChange	= (float) rand() / (float) RAND_MAX;

	attacking			= false;
	attackTimer			= 0.0f;

	health				= 3;
	dead				= false;
	
}

// Called every frame
void AEnemy::Tick( float DeltaTime ) {

	if(dead) return;

	static const float attackTime = 0.7f;

	if(!player) {

		for(TActorIterator<AmainCharacter> ActorItr(GetWorld()); ActorItr; ++ActorItr) {

			player = *ActorItr;

		}

	}

	actionTimer += DeltaTime;
	if(actionTimer > actionTimeChange) {
		
		action				= rand() % 2;
		actionTimeChange	= 2.0f * (float) rand() / (float) RAND_MAX;
		actionTimer			= 0.0f;

	}

	attackTimer += DeltaTime;
	if(attackTimer > attackTime) {
	
		if(animationInstance) animationInstance->Hit = false;
		attacking = false;

	}
	

	if(player) {

		FVector deltaLocation = player->GetActorLocation() - GetActorLocation();

		if(!player->isTransformed()) {
			
			float walking = 0.0f;
			float playerDistance = deltaLocation.Size();
			if(action == 1 && !attacking && playerDistance < 1000.0f && playerDistance > 100.0f) {
				
				AddMovementInput(deltaLocation.GetSafeNormal(),  60.0f * DeltaTime);
				walking = 1.0f;
			}


			if(animationInstance) {
			
				animationInstance->Speed = FMath::Lerp(animationInstance->Speed, walking, 0.04f);
		
			}

			if(playerDistance < 1000.0f && attackTimer > attackTime) {

				// Rotation
				float wantedRotation = 90.0f + (180.0f / (float) PI) * atan2(deltaLocation.Y, deltaLocation.X);

				// Keep in range
				while(wantedRotation	< 0.0f)			wantedRotation += 360.0f;
				while(wantedRotation	> 360.0f)		wantedRotation -= 360.0f;
				while(characterRotation	< 0.0f)			characterRotation += 360.0f;
				while(characterRotation	> 360.0f)		characterRotation -= 360.0f;
		

				// Get closest
				if(fabs(characterRotation - wantedRotation) > fabs(characterRotation - (wantedRotation + 360.0f))) wantedRotation += 360.0f;
				if(fabs(characterRotation - wantedRotation) > fabs(characterRotation - (wantedRotation - 360.0f))) wantedRotation -= 360.0f;


				// Rotate
				characterRotation = FMath::Lerp(characterRotation, wantedRotation, 0.06f);

			}
			
			FVector forwardVector = FVector(cos((characterRotation - 90.0f) * PI / 180.0f), sin((characterRotation - 90.0f) * PI / 180.0f), 0.0f);
			if(playerDistance < 250.0f && action == 1 && FVector::DotProduct(forwardVector, deltaLocation.GetSafeNormal()) > 0.85f && !attacking) {
				
				if(animationInstance) {
				
					animationInstance->Hit = true;
					attackTimer = 0.0f;
					attacking = true;

				}

				actionTimeChange = 0.0f;

			}
		
		}

		
		if(attackTimer < attackTime) {
			
			AddMovementInput(FVector(cos((characterRotation - 90.0f) * PI / 180.0f), sin((characterRotation - 90.0f) * PI / 180.0f), 0.0f),	40.0f * DeltaTime);

		} 

		if(humanMesh) humanMesh->SetWorldRotation(FRotator(0.0f, characterRotation, 0.0f));


		if(hitForce > 0.0f) {
		
			hitForce = fmax(hitForce - 200.0f * DeltaTime, 0.0f);

		}

	}

	Super::Tick( DeltaTime );

}

// Called to bind functionality to input
void AEnemy::SetupPlayerInputComponent(class UInputComponent* InputComponent)
{
	Super::SetupPlayerInputComponent(InputComponent);

}


void AEnemy::hit() {

	if(player) {

		if(FVector::Dist(GetActorLocation(), player->GetActorLocation()) < 150.0f) {

			health--;

			if(health <= 0) {

				if(animationInstance) animationInstance->Die = true;
				dead = true;

			}
		
		}

	}

}


UActorComponent *AEnemy::GetComponentByName(const char *pName) {
	
	auto components =  GetComponents();
	for(auto component : components) {
		
		if(component->GetName() == pName) return component;

	}

	return nullptr;

}


