#include "PlayerControllerBase.h"
#include "Common.h"
#include "Tangible.h"
#include "TangibleManager.h"
#include "Kismet/GameplayStatics.h"
#include "Engine/GameInstance.h"

AlxPlayerControllerBase *AlxPlayerControllerBase::FromContext(const UObject *Context)
{
	APlayerController *PC = Context->GetWorld()->GetFirstPlayerController();
	AlxPlayerControllerBase *Result = Cast<AlxPlayerControllerBase>(PC);
	if (Result == nullptr)
	{
		UE_LOG(LogLuprexIntegration, Fatal, TEXT("Not currently using a Luprex Player Controller."));
	}
	return Result;
}

const FHitResult &AlxPlayerControllerBase::GetLookAt(const UObject *Context)
{
	return FromContext(Context)->CurrentLookAt;
}

const AActor *AlxPlayerControllerBase::GetLookAtActor(const UObject *Context)
{
	return FromContext(Context)->CurrentLookAt.GetActor();
}

void AlxPlayerControllerBase::SetLookAt(const UObject *Context, const FHitResult &HitResult)
{
	AlxPlayerControllerBase *PC = FromContext(Context);
	if (PC->CurrentLookAt.HitObjectHandle != HitResult.HitObjectHandle)
	{
		PC->MustCallLookAtChanged = true;
	}
	PC->CurrentLookAt = HitResult;
}

void AlxPlayerControllerBase::SetLookAtChanged(const UObject *Context)
{
	AlxPlayerControllerBase *PC = FromContext(Context);
	PC->MustCallLookAtChanged = true;
}

FVector2D AlxPlayerControllerBase::GetLookAtPixel(const UObject *Context)
{
	AlxPlayerControllerBase *PC = FromContext(Context);
	FVector2D ScreenPosition;
	if (!UGameplayStatics::ProjectWorldToScreen(PC, PC->CurrentLookAt.Location, ScreenPosition, false))
	{
		return FVector2D();
	}
	return ScreenPosition;
}

void AlxPlayerControllerBase::UpdateLookAt()
{
	UlxTangibleManager *TM = GetGameInstance()->GetSubsystem<UlxTangibleManager>();
	if (TM == nullptr) return;
	UlxTangible *Possessed = TM->GetPossessedTangible();
	if (Possessed == nullptr) return;
	APawn *Pawn = GetPawn();
	if (Pawn == nullptr) return;
	if (Possessed->GetActor() != Cast<AActor>(Pawn)) return;
	if (PlayerCameraManager == nullptr) return;

	CalculateLookAt();

	if (MustCallLookAtChanged)
	{
		MustCallLookAtChanged = false;
		LookAtChanged();
	}
}
