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


#include "Player/ExoPlayerController.h"
#include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h"
#include "Characters/ExoPlayerCharacter.h"
#include "GameFramework/Character.h"
#include "GameFramework/CharacterMovementComponent.h"

AExoPlayerController::AExoPlayerController()
{
	PrimaryActorTick.bCanEverTick = true;
}

void AExoPlayerController::BeginPlay()
{
	Super::BeginPlay();
	check(InputContext);
	
	PlayerCharacter = Cast<AExoPlayerCharacter>(GetPawn<ACharacter>());
	check(PlayerCharacter);
	
	UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(GetLocalPlayer());

	if (Subsystem)
	{
		Subsystem->AddMappingContext(InputContext, 0);
	}
	
	InteractionComponent = PlayerCharacter->FindComponentByClass<UInteractionComponent>();
	ShootingComponent = PlayerCharacter->FindComponentByClass<UShootingComponent>();

	// Ustawianie w komponencie poruszania pr�dko�ci zapisanej w characterze
	PlayerCharacter->GetCharacterMovement()->MaxWalkSpeed = PlayerCharacter->WalkSpeed;
}

void AExoPlayerController::PlayerTick(float DeltaTime)
{
	Super::PlayerTick(DeltaTime);
	
}

void AExoPlayerController::SetupInputComponent()
{
	Super::SetupInputComponent();

	UEnhancedInputComponent* EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(InputComponent);

	EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Triggered, this, &AExoPlayerController::Move);
	EnhancedInputComponent->BindAction(LookAction, ETriggerEvent::Triggered, this, &AExoPlayerController::Look);
	EnhancedInputComponent->BindAction(InteractAction, ETriggerEvent::Triggered, this, &AExoPlayerController::Interact);
	EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Started, this, &AExoPlayerController::PlayerJump);
	EnhancedInputComponent->BindAction(DodgeAction, ETriggerEvent::Started, this, &AExoPlayerController::PlayerDodge);
	EnhancedInputComponent->BindAction(CrouchAction, ETriggerEvent::Started, this, &AExoPlayerController::PlayerStartCrouch);
	EnhancedInputComponent->BindAction(CrouchAction, ETriggerEvent::Completed, this, &AExoPlayerController::PlayerStopCrouch);
	EnhancedInputComponent->BindAction(SprintAction, ETriggerEvent::Started, this, &AExoPlayerController::PlayerStartSprint);
	EnhancedInputComponent->BindAction(SprintAction, ETriggerEvent::Completed, this, &AExoPlayerController::PlayerStopSprint);
	EnhancedInputComponent->BindAction(ShootAction, ETriggerEvent::Started, this, &AExoPlayerController::PlayerShoot);
	EnhancedInputComponent->BindAction(AimAction, ETriggerEvent::Started, this, &AExoPlayerController::PlayerAim);
	EnhancedInputComponent->BindAction(MeleAction, ETriggerEvent::Started, this, &AExoPlayerController::PlayerMeleAttack);
	EnhancedInputComponent->BindAction(ChangeWeaponAction, ETriggerEvent::Started, this, &AExoPlayerController::PlayerChangeWeapon);
	EnhancedInputComponent->BindAction(SelectFirstWeaponAction, ETriggerEvent::Started, this, &AExoPlayerController::PlayerSelectFirstWeapon);
	EnhancedInputComponent->BindAction(SelectSecondWeaponAction, ETriggerEvent::Started, this, &AExoPlayerController::PlayerSelectSecondWeapon);
	EnhancedInputComponent->BindAction(DropWeaponAction, ETriggerEvent::Started, this, &AExoPlayerController::PlayerDropWeapon);
	EnhancedInputComponent->BindAction(ReloadAction, ETriggerEvent::Started, this, &AExoPlayerController::PlayerReload);
}

void AExoPlayerController::Move(const FInputActionValue& InputActionValue)
{
	const FVector2D InputAxisVector = InputActionValue.Get<FVector2D>();
	const FRotator Rotation = GetControlRotation();
	const FRotator YawRotation(0.f, Rotation.Yaw, 0.f);

	const FVector ForwardDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
	const FVector RightDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);

	if (PlayerCharacter)
	{
		PlayerCharacter->AddMovementInput(ForwardDirection, InputAxisVector.X);
		PlayerCharacter->AddMovementInput(RightDirection, InputAxisVector.Y);
	}
}

void AExoPlayerController::Look(const FInputActionValue& InputActionValue)
{
	FVector2D InputAxisVector = InputActionValue.Get<FVector2D>();

	AddYawInput(InputAxisVector.X);
	AddPitchInput(InputAxisVector.Y);
}


void AExoPlayerController::Interact()
{
	if (InteractionComponent->InteractedActor)
		IInteractable::Execute_Interact(InteractionComponent->InteractedActor, PlayerCharacter);
}

void AExoPlayerController::PlayerJump()
{
	PlayerCharacter->Jump();
}

void AExoPlayerController::PlayerDodge()
{
	UE_LOG(LogTemp, Error, TEXT("Player Dodge"));
	
	if (PlayerCharacter->GetCharacterMovement()->IsFalling()) return;

	if (PlayerCharacter->GetCharacterMovement()->IsCrouching()) return;

	if (!CanDodge) return;

	CanDodge = false;
	
	FVector DodgeDirection = PlayerCharacter->GetVelocity().GetSafeNormal();
	DodgeDirection.Z = 0.f;

	if (DodgeDirection.IsNearlyZero())
		DodgeDirection = PlayerCharacter->GetActorForwardVector();

	PlayerCharacter->LaunchCharacter(DodgeDirection * PlayerCharacter->DodgeForce, true, true);
	
	GetWorldTimerManager().SetTimer(DodgeCooldownTimer, this, &AExoPlayerController::ResetDodge, PlayerCharacter->DodgeCooldown, false);
}

void AExoPlayerController::ResetDodge()
{
	CanDodge = true;
}

void AExoPlayerController::PlayerStartCrouch()
{
	PlayerCharacter->Crouch();
}

void AExoPlayerController::PlayerStopCrouch()
{
	PlayerCharacter->UnCrouch();
}

void AExoPlayerController::PlayerStartSprint()
{
	UE_LOG(LogTemp, Display, TEXT("Start sprint"));

	PlayerCharacter->GetCharacterMovement()->MaxWalkSpeed = PlayerCharacter->SprintSpeed;
}

void AExoPlayerController::PlayerStopSprint()
{
	UE_LOG(LogTemp, Display, TEXT("Stop sprint"));

	PlayerCharacter->GetCharacterMovement()->MaxWalkSpeed = PlayerCharacter->WalkSpeed;
}

void AExoPlayerController::PlayerShoot()
{
	ShootingComponent->Shoot();
}

void AExoPlayerController::PlayerAim()
{
	
}

void AExoPlayerController::PlayerMeleAttack()
{
	ShootingComponent->MeleAttack();
}

void AExoPlayerController::PlayerChangeWeapon()
{
	ShootingComponent->SwitchGun();
}

void AExoPlayerController::PlayerSelectFirstWeapon()
{
	ShootingComponent->SelectGun(true);
}

void AExoPlayerController::PlayerSelectSecondWeapon()
{
	ShootingComponent->SelectGun(false);
}

void AExoPlayerController::PlayerDropWeapon()
{
	ShootingComponent->DropGun();
}

void AExoPlayerController::PlayerReload()
{
	ShootingComponent->Reload();
}
