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


#include "RollaBallPlayer.h"
#include "GameFramework/SpringArmComponent.h"
#include "Camera/CameraComponent.h"
#include "../../../../Plugins/EnhancedInput/Source/EnhancedInput/Public/EnhancedInputComponent.h"
#include "Delegates/Delegate.h"
#include "Components/SphereComponent.h"
#include "RollaBallWidget.h"
#include "Components/SplineComponent.h"
#include "LevelManager.h"
#include "EngineUtils.h"

// Sets default values
ARollaBallPlayer::ARollaBallPlayer()
{
 	// Set this pawn to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

	Mesh=CreateDefaultSubobject<UStaticMeshComponent>("Mesh");
	SpringArm =CreateDefaultSubobject<USpringArmComponent>("SpringArm");
	Camera =CreateDefaultSubobject<UCameraComponent>("Camera");
	Sphere = CreateDefaultSubobject<USphereComponent>( "Sphere" );
	SphereTrigger = CreateDefaultSubobject<USphereComponent>( "SphereTrigger" );

	RootComponent = Sphere;

	Mesh->SetupAttachment( Sphere );
	SphereTrigger->SetupAttachment( Sphere );
	SpringArm->SetupAttachment( Sphere );

	Camera->SetupAttachment( SpringArm );

	Sphere->SetSimulatePhysics( true );
	Sphere->SetNotifyRigidBodyCollision( true );

	SphereTrigger->SetSimulatePhysics( false );
	SphereTrigger->SetNotifyRigidBodyCollision( false );
	SphereTrigger->SetGenerateOverlapEvents( true );
}

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

	MoveForce *= Sphere->GetMass();
	JumpImpulse *= Sphere->GetMass();

	SphereTrigger->SetSphereRadius( Sphere->GetScaledSphereRadius() + 0.05f * Sphere->GetScaledSphereRadius() );

 	Sphere->OnComponentHit.AddDynamic( this, &ARollaBallPlayer::OnHittt );
	SphereTrigger->OnComponentBeginOverlap.AddDynamic( this, &ARollaBallPlayer::OnEnterFloor );
	SphereTrigger->OnComponentEndOverlap.AddDynamic( this, &ARollaBallPlayer::OnLeavingFloor );

	GameManager = ( AMyGameModeBase* )GetWorld()->GetAuthGameMode();

	for( TActorIterator<ALevelManager> It( GetWorld() ); It; ++It )
	{
		ALevelManager* itLevelManager = *It;
		if( itLevelManager )
		{
			LevelManager = itLevelManager;
		}
	}

	if( LevelManager )
	{
		Spline = (USplineComponent*) LevelManager->Spline->GetComponentByClass( USplineComponent::StaticClass() );
		MaxSplineDistance = Spline->GetSplineLength();
	}

// 	pWidgetRef = CreateWidget<URollaBallWidget>(GetWorld(), pWidget);

	if( pWidgetRef )
		pWidgetRef->AddToViewport();
}

void ARollaBallPlayer::Tick( float DeltaTime )
{
	Super::Tick( DeltaTime );

	float distance = Spline->GetDistanceAlongSplineAtLocation(this->GetActorLocation(), ESplineCoordinateSpace::World);

	if( GameManager )
	{
		float NewTimer = GameManager->GetTimer();

		if( pWidgetRef )
		{
			pWidgetRef->SetTimerText( NewTimer );
			pWidgetRef->SetProgress( distance / MaxSplineDistance );
		}
	}
}

// Called to bind functionality to input
void ARollaBallPlayer::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	UEnhancedInputComponent* Input = Cast<UEnhancedInputComponent>( PlayerInputComponent );
 	Input->BindAction( JumpAction, ETriggerEvent::Triggered, this, &ARollaBallPlayer::JumpFct );
	Input->BindAction( MoveAction, ETriggerEvent::Triggered, this, &ARollaBallPlayer::MoveForward );
}

void ARollaBallPlayer::MoveForward( const FInputActionValue& Value )
{
	if( bIsOnGround )
	{
		FVector moveValue = Value.Get<FVector>();
		Sphere->AddForce( moveValue * MoveForce );
	}
}

void ARollaBallPlayer::JumpFct( const FInputActionValue& Value )
{
	if( JumpCount < MaxJumpCount )
	{
		JumpCount++;
		Sphere->AddImpulse( FVector( 0, 0, JumpImpulse ) );
	}
}

void ARollaBallPlayer::OnHittt( UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit )
{
	JumpCount = 0;

	if( OtherActor->ActorHasTag( "Trap" ) )
	{
		GameManager->GameOver();
	}
}

void ARollaBallPlayer::OnLeavingFloor( UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex )
{
	bIsOnGround = false;
}

void ARollaBallPlayer::OnEnterFloor( UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult )
{
	bIsOnGround = true;
}

