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


#include "MyCharacter.h"

#include "EnhancedInputSubsystems.h"
#include "EnhancedInputComponent.h"
#include "GameFramework/CharacterMovementComponent.h"

#include "CameraPawn.h"

void AMyCharacter::Move(const FInputActionValue& Value)
{
	auto f2d = Value.Get<FVector2D>();

	// 移动
	auto f = FRotator(0, GetControlRotation().Yaw, 0).Vector();
	auto r = -f.Cross(FVector::UpVector);
	AddMovementInput(f * f2d.X);
	AddMovementInput(r * f2d.Y);

	// 转向
	if (f2d.SizeSquared() > 0.01f)
	{
		FRotator Rot = FVector(f2d.X, f2d.Y, 0).Rotation() + FRotator(0, GetControlRotation().Yaw, 0);
		float InterpSpeed = 10.0f;
		FRotator NewRotation = FMath::RInterpTo(GetActorRotation(), Rot, GetWorld()->GetDeltaSeconds(), InterpSpeed);
		SetActorRotation(NewRotation);
	}
}

void AMyCharacter::BeginRun(const FInputActionValue& Value)
{
	bIsRunning = true;
	GetCharacterMovement()->MaxWalkSpeed = 1200.0f;
}
void AMyCharacter::StopRun(const FInputActionValue& Value)
{
	bIsRunning = false;
	GetCharacterMovement()->MaxWalkSpeed = 600.0f;
}

void AMyCharacter::BeginCrouch(const FInputActionValue& Value)
{
	bIsCrouching = true;
	GetCharacterMovement()->bWantsToCrouch = true;
	GetCharacterMovement()->Crouch();
	UE_LOG(LogTemp, Warning, TEXT("Crouching"));
}

void AMyCharacter::StopCrouch(const FInputActionValue& Value)
{
	bIsCrouching = false;
	GetCharacterMovement()->bWantsToCrouch = false;
	GetCharacterMovement()->UnCrouch();
	UE_LOG(LogTemp, Warning, TEXT("Stop Crouch"));
}

void AMyCharacter::CameraMove(const FInputActionValue& Value)
{
	if (CameraActor)
	{
		CameraActor->CameraMove(Value);
	}
}

void AMyCharacter::CameraRotate(const FInputActionValue& Value)
{
	if (CameraActor)
	{
		CameraActor->CameraRotate(Value);
	}
}

void AMyCharacter::CameraZoom(const FInputActionValue& Value)
{
	if (CameraActor)
	{
		CameraActor->CameraZoom(Value);
	}
}

void AMyCharacter::CameraReset(const FInputActionValue& Value)
{
	if (CameraActor)
	{
		CameraActor->CameraReset(Value);
	}
}

// Sets default values
AMyCharacter::AMyCharacter()
{
 	// 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;

	GetCharacterMovement()->GetNavAgentPropertiesRef().bCanCrouch = true;

	// 禁用控制器旋转
	bUseControllerRotationPitch = false;
	bUseControllerRotationYaw = false;
	bUseControllerRotationRoll = false;
}

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

	auto w = GetWorld();
	ACameraPawn* temp = nullptr;
	if (w)
	{
		UClass* CameraClass;
		if (CameraActorClass)
		{
			CameraClass = CameraActorClass;
		}
		else
		{
			CameraClass = ACameraPawn::StaticClass();
		}
		FTransform SpawnTransform(GetActorRotation(), GetActorLocation());
		temp = w->SpawnActorDeferred<ACameraPawn>(CameraClass, SpawnTransform);
		/*temp->SetActorRotation(FRotator(-60.0f, 0.0f, 0.0f));*/
		temp->FollowTarget = this;
		temp->FinishSpawning(SpawnTransform);
	}
	if (temp)
	{
		CameraActor = temp;
	}
}

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

}

// Called to bind functionality to input
void AMyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);

	auto PlayerController = Cast<APlayerController>(GetController());
	UEnhancedInputLocalPlayerSubsystem* Subsystem = NULL;
	if (PlayerController)
	{
		Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer());
	}
	if (Subsystem && DefaultMapping)
	{
		Subsystem->AddMappingContext(DefaultMapping, 0);
	}

	auto EnhancedInputComponent = Cast<UEnhancedInputComponent>(PlayerInputComponent);
	if (EnhancedInputComponent)
	{
		if (MoveAction) {
			EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Triggered, this, &AMyCharacter::Move);
		}
		if (RunAction) {
			EnhancedInputComponent->BindAction(RunAction, ETriggerEvent::Started, this, &AMyCharacter::BeginRun);
			EnhancedInputComponent->BindAction(RunAction, ETriggerEvent::Completed, this, &AMyCharacter::StopRun);
		}
		if (CrouchAction) {
			EnhancedInputComponent->BindAction(CrouchAction, ETriggerEvent::Started, this, &AMyCharacter::BeginCrouch);
			EnhancedInputComponent->BindAction(CrouchAction, ETriggerEvent::Completed, this, &AMyCharacter::StopCrouch);
		}
		if (CameraMoveAction)
		{
			EnhancedInputComponent->BindAction(CameraMoveAction, ETriggerEvent::Triggered, this, &AMyCharacter::CameraMove);
		}
		if (CameraZoomAction)
		{
			EnhancedInputComponent->BindAction(CameraZoomAction, ETriggerEvent::Triggered, this, &AMyCharacter::CameraZoom);
		}
		if (CameraResetAction)
		{
			EnhancedInputComponent->BindAction(CameraResetAction, ETriggerEvent::Triggered, this, &AMyCharacter::CameraReset);
		}
		if (CameraRotateAction)
		{
			EnhancedInputComponent->BindAction(CameraRotateAction, ETriggerEvent::Triggered, this, &AMyCharacter::CameraRotate);
		}
	}
}

