// Multiplayer By Caleb


#include "Crunch/Public/Character/CPlayerCharacter.h"

#include "AbilitySystemComponent.h"
#include "Camera/CameraComponent.h"
#include "Crunch/Public/Player/CPlayerController.h"
#include "GameFramework/SpringArmComponent.h"
#include "EnhancedInputSubsystems.h"
#include "EnhancedInputComponent.h"
#include "GameFramework/CharacterMovementComponent.h"


ACPlayerCharacter::ACPlayerCharacter()
{
	PrimaryActorTick.bCanEverTick = true;

	CameraBoom = CreateDefaultSubobject<USpringArmComponent>("CameraBoom");
	CameraBoom->SetupAttachment(GetRootComponent());
	CameraBoom->bUsePawnControlRotation = true;

	ViewCamera = CreateDefaultSubobject<UCameraComponent>("ViewCamera");
	ViewCamera->SetupAttachment(CameraBoom, USpringArmComponent::SocketName);

	bUseControllerRotationYaw = false;
	GetCharacterMovement()->bOrientRotationToMovement = true;
	GetCharacterMovement()->RotationRate = RotationRate;
}

void ACPlayerCharacter::PawnClientRestart()
{
	Super::PawnClientRestart();

	if (const auto OwningPlayerController{GetController<ACPlayerController>()})
	{
		const auto InputSubsystem{
			OwningPlayerController->GetLocalPlayer()->GetSubsystem<UEnhancedInputLocalPlayerSubsystem>()
		};
		if (InputSubsystem)
		{
			InputSubsystem->RemoveMappingContext(GameplayMappingContext);
			InputSubsystem->AddMappingContext(GameplayMappingContext, 0);
		}
	}
}

void ACPlayerCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);
	if (const auto EnhancedInputComp{Cast<UEnhancedInputComponent>(PlayerInputComponent)})
	{
		EnhancedInputComp->BindAction(JumpInputAction, ETriggerEvent::Triggered, this, &ThisClass::Jump);
		EnhancedInputComp->BindAction(LookInputAction, ETriggerEvent::Triggered, this, &ThisClass::HandleLookInput);
		EnhancedInputComp->BindAction(MoveInputAction, ETriggerEvent::Triggered, this, &ThisClass::HandleMoveInput);

		for (const auto InputIdPair : GameplayAbilityInputActions)
		{
			EnhancedInputComp->BindAction(
				InputIdPair.Value,
				ETriggerEvent::Triggered,
				this,
				&ThisClass::HandleAbilityInput,
				InputIdPair.Key
			);
		}
	}
}

void ACPlayerCharacter::HandleLookInput(const FInputActionValue& InputActionValue)
{
	const FVector2D InputVal{InputActionValue.Get<FVector2D>()};

	AddControllerPitchInput(-InputVal.Y);
	AddControllerYawInput(InputVal.X);
}

void ACPlayerCharacter::HandleMoveInput(const FInputActionValue& InputActionValue)
{
	FVector2D InputVal{InputActionValue.Get<FVector2D>()};
	InputVal.Normalize();

	AddMovementInput(GetMoveFwdDir() * InputVal.Y + GetLookRightDir() * InputVal.X);
}

void ACPlayerCharacter::HandleAbilityInput(const FInputActionValue& InputActionValue, ECAbilityInputID InputID)
{
	const bool bPressed{InputActionValue.Get<bool>()};
	const auto AbilitySystemComponent{GetAbilitySystemComponent()};
	bPressed
		? AbilitySystemComponent->AbilityLocalInputPressed(static_cast<int32>(InputID))
		: AbilitySystemComponent->AbilityLocalInputReleased(static_cast<int32>(InputID));
}

void ACPlayerCharacter::OnDead()
{
	if (const auto PlayerController { GetController<APlayerController>() })
	{
		DisableInput(PlayerController);
	}
}

void ACPlayerCharacter::OnRespawn()
{
	if (const auto PlayerController { GetController<APlayerController>() })
	{
		EnableInput(PlayerController);
	}
}

FVector ACPlayerCharacter::GetLookRightDir() const
{
	return ViewCamera->GetRightVector();
}

FVector ACPlayerCharacter::GetLookFwdDir() const
{
	return ViewCamera->GetForwardVector();
}

FVector ACPlayerCharacter::GetMoveFwdDir() const
{
	return FVector::CrossProduct(GetLookRightDir(), FVector::UpVector);
}
