// © 2024 Long Ly. All rights reserved. Any unauthorized use, reproduction, or distribution of this trademark is strictly prohibited and may result in legal action.


#include "Characters/OLSCharacter.h"

#include "Characters/Components/OLSCharacterMovementComponent.h"
#include "Components/OLSLocomotionComponent.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "GameFramework/PawnMovementComponent.h"


// Sets default values

AOLSCharacter::AOLSCharacter(const FObjectInitializer& objectInitializer) : Super(
	objectInitializer.SetDefaultSubobjectClass<UOLSCharacterMovementComponent>(
		CharacterMovementComponentName))
{
	PrimaryActorTick.bCanEverTick = false;
	PrimaryActorTick.bStartWithTickEnabled = false;
	
	NetCullDistanceSquared = 900000000.0f;

	LocomotionComponent = CreateDefaultSubobject<UOLSLocomotionComponent>(TEXT("Locomotion Component"));
}

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

	InitializeSystems();
}

void AOLSCharacter::InitializeSystems()
{
	if (LocomotionComponent)
	{
		LocomotionComponent->GetOnRotationModeChangedNativeDelegate().AddUObject(this, &ThisClass::OnRotationModeChanged);

		LocomotionComponent->Initialize();
	}
}

// Called every frame
void AOLSCharacter::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
}

// Called to bind functionality to input
void AOLSCharacter::SetupPlayerInputComponent(UInputComponent* playerInputComponent)
{
	Super::SetupPlayerInputComponent(playerInputComponent);
}

UPawnMovementComponent* AOLSCharacter::GetMovementComponent() const
{
	return Cast<UPawnMovementComponent>(GetCharacterMovement());
}

UOLSLocomotionComponent* AOLSCharacter::GetLocomotionComponent() const
{
	return LocomotionComponent;
}

float AOLSCharacter::GetMaxAcceleration() const
{
	return GetCharacterMovement()->GetMaxAcceleration();
}

FVector AOLSCharacter::GetCurrentAcceleration() const
{
	return GetCharacterMovement()->GetCurrentAcceleration();
}

EMovementMode AOLSCharacter::GetMovementMode() const
{
	return GetCharacterMovement()->MovementMode;
}

void AOLSCharacter::SetMaxWalkSpeed(const float newMaxWalkSpeed)
{
	GetCharacterMovement()->MaxWalkSpeed = newMaxWalkSpeed;
}

bool AOLSCharacter::IsOrientRotationToMovement() const
{
	return GetCharacterMovement()->bOrientRotationToMovement;
}

UAnimInstance* AOLSCharacter::GetAnimInstance() const
{
	return (GetMesh() ? GetMesh()->GetAnimInstance() : nullptr);
}

void AOLSCharacter::OnRotationModeChanged(const EOLSRotationMode& prevrRotationMode)
{
	switch (LocomotionComponent->GetRotationMode())
	{
	case EOLSRotationMode::EVelocityDirection:
		GetCharacterMovement()->bOrientRotationToMovement = true;
		bUseControllerRotationYaw = false;
		GetCharacterMovement()->bUseControllerDesiredRotation = false;
		break;
	case EOLSRotationMode::ELookingDirection:
		GetCharacterMovement()->bOrientRotationToMovement = false;
		bUseControllerRotationYaw = true;
		GetCharacterMovement()->bUseControllerDesiredRotation = false;
		break;
	case EOLSRotationMode::EAiming:
		GetCharacterMovement()->bOrientRotationToMovement = false;
		bUseControllerRotationYaw = true;
		GetCharacterMovement()->bUseControllerDesiredRotation = true;
		break;
	}
}
