// Copyright Epic Games, Inc. All Rights Reserved.

#include "MovementComponentState.h"
#include "Animation/AnimInstance.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "Tangible.h"

FlxMovementComponentState::FlxMovementComponentState(UCharacterMovementComponent *CMC)
{
	Velocity = CMC->Velocity;
	bIsAccelerating = !CMC->GetCurrentAcceleration().IsNearlyZero();
	MaxWalkSpeed = CMC->MaxWalkSpeed;
	MovementMode = CMC->MovementMode;
	bIsFalling = CMC->IsFalling();
	bIsCrouching = CMC->IsCrouching();
}

FString UlxMovementComponentStateLibrary::DebugString(const FlxMovementComponentState &State)
{
	const UEnum *ModeEnum = StaticEnum<EMovementMode>();
	FString ModeName = ModeEnum ? ModeEnum->GetNameStringByValue(State.MovementMode.GetValue()) : FString::FromInt(State.MovementMode.GetValue());
	ModeName.RemoveFromStart(TEXT("MOVE_"));
	return FString::Printf(TEXT("Vel=(%.1f, %.1f, %.1f) MaxWalk=%.1f Mode=%s Accel=%s Fall=%s Crouch=%s"),
		State.Velocity.X, State.Velocity.Y, State.Velocity.Z,
		State.MaxWalkSpeed,
		*ModeName,
		State.bIsAccelerating ? TEXT("true") : TEXT("false"),
		State.bIsFalling ? TEXT("true") : TEXT("false"),
		State.bIsCrouching ? TEXT("true") : TEXT("false"));
}

bool UlxMovementComponentStateLibrary::GetShouldMove(const FlxMovementComponentState &State)
{
	return State.bIsAccelerating && State.Velocity.Size2D() >= 3.0;
}

FlxMovementComponentState UlxMovementComponentStateLibrary::GetMovementComponentState(UAnimInstance *AnimInstance)
{
	if (!AnimInstance) return FlxMovementComponentState();

	AActor *Actor = AnimInstance->GetOwningActor();
	if (!Actor) return FlxMovementComponentState();

	UCharacterMovementComponent *CMC = Actor->FindComponentByClass<UCharacterMovementComponent>();
	if (CMC && CMC->MovementMode != MOVE_None) return FlxMovementComponentState(CMC);

	UlxTangible *Tangible = UlxTangible::GetActorTangibleQuiet(Actor);
	if (Tangible) return Tangible->FakeMovementComponentState;

	if (CMC) return FlxMovementComponentState(CMC);
	return FlxMovementComponentState();
}

FlxMovementComponentState UlxMovementComponentStateLibrary::SetFakeMovementComponentState(AActor *Actor, const FlxMovementComponentState &State)
{
	if (!Actor) return State;
	UlxTangible *Tangible = UlxTangible::GetActorTangibleOrLog(Actor);
	if (Tangible)
	{
		UE_LOG(LogTemp, Display, TEXT("SetFakeMovementComponentState(%s): %s"), *Actor->GetName(), *DebugString(State));
		Tangible->FakeMovementComponentState = State;
	}
	return State;
}

FFormatArgumentData UlxMovementComponentStateLibrary::FormatArgumentDataMovementComponentState(const FlxMovementComponentState &AutoConvertedValue, const FString &Name)
{
	FFormatArgumentData Result;
	Result.ArgumentValueType = EFormatArgumentType::Text;
	Result.ArgumentName = Name;
	Result.ArgumentValue = FText::FromString(DebugString(AutoConvertedValue));
	return Result;
}
