void ABatteryCollectorGameMode::HandleNewState(EBatteryPlayState NewState)
{
    switch (NewState)
    {
        // If the game is playing
    case EBatteryPlayState::EPlaying:
    {
        // spawn volumes active
        for (ASpawnVolume* Volume : SpawnVolumeActors)
        {
            Volume->SetSpawningActive(true);
        }
    }
    break;
    // If we've won the game
    case EBatteryPlayState::EWon:
    {
        // spawn volumes inactive
        for (ASpawnVolume* Volume : SpawnVolumeActors)
        {
            Volume->SetSpawningActive(false);
        }
    }
    break;
    // If we've lost the game
    case EBatteryPlayState::EGameOver:
    {
        // spawn volumes inactive
        for (ASpawnVolume* Volume : SpawnVolumeActors)
        {
            Volume->SetSpawningActive(false);
        }
        // block player input
        APlayerController* PlayerController = UGameplayStatics::GetPlayerController(this, 0);
        if (PlayerController)
        {
            PlayerController->SetCinematicMode(true, false, false, true, true);
        }
        // ragdoll the character
        ACharacter* MyCharacter = UGameplayStatics::GetPlayerCharacter(this, 0);
        if (MyCharacter)
        {
            MyCharacter->GetMesh()->SetSimulatePhysics(true);
            MyCharacter->GetMovementComponent()->MovementState.bCanJump = false;
        }
    }
    break;
    // Unknown/default state
    default:
    case EBatteryPlayState::EUnknown:
    {
        // do nothing
    }
    break;
    }

}
void AAssignment_1GameMode::HandleCurrentState(EBatteryPlayState NewState)
{
    switch (NewState)
    {
        // If the game is playing
        case EBatteryPlayState::EPlaying:
        {
            // Spawn Volumes Active
            for (ASpawnVolume * Volume : SpawnVolumeActors)
            {
                Volume->SetSpawningActive(true);
            }
        }
        break;
        // If we've won the game
        case EBatteryPlayState::EWon:
        {
            // Spawn Volumes Inactive
            for (ASpawnVolume * Volume : SpawnVolumeActors)
            {
                Volume->SetSpawningActive(false);
            }
        }
        break;
        // If we've lost the game
        case EBatteryPlayState::EGameOver:
        {
            // Spawn Volumes Inactives
            for (ASpawnVolume * Volume : SpawnVolumeActors)
            {
                Volume->SetSpawningActive(false);
            }
            // Block Player Input
            APlayerController * PlayerController = UGameplayStatics::GetPlayerController(this, 0);
            if (PlayerController)
            {
                PlayerController->SetCinematicMode(true, true, true);
            }
            // Ragdoll the character
            ACharacter* MyCharacter = UGameplayStatics::GetPlayerCharacter(this, 0);
            if (MyCharacter)
            {
                MyCharacter->GetMesh()->SetSimulatePhysics(true);
                MyCharacter->GetMovementComponent()->MovementState.bCanJump = false;
            }
        }
        break;
        // Debug
        default:
        case EBatteryPlayState::EUnknown:
        {
            // Do nothing
        }
        break;
    }
}
//TODO: This is still an awful way to do this and we should scrap this task or do it right.
void UAbilityTask_MoveToLocation::TickTask(float DeltaTime)
{
	if (bIsFinished)
	{
		return;
	}

	Super::TickTask(DeltaTime);
	AActor* MyActor = GetAvatarActor();
	if (MyActor)
	{
		ACharacter* MyCharacter = Cast<ACharacter>(MyActor);
		if (MyCharacter)
		{
			UCharacterMovementComponent* CharMoveComp = Cast<UCharacterMovementComponent>(MyCharacter->GetMovementComponent());
			if (CharMoveComp)
			{
				CharMoveComp->SetMovementMode(MOVE_Custom, 0);
			}
		}


		float CurrentTime = GetWorld()->GetTimeSeconds();

		if (CurrentTime >= TimeMoveWillEnd)
		{
			bIsFinished = true;

			// Teleport in attempt to find a valid collision spot
			MyActor->TeleportTo(TargetLocation, MyActor->GetActorRotation());
			if (!bIsSimulating)
			{
				MyActor->ForceNetUpdate();
				OnTargetLocationReached.Broadcast();
				EndTask();
			}
		}
		else
		{
			float MoveFraction = (CurrentTime - TimeMoveStarted) / DurationOfMovement;
			if (LerpCurve)
			{
				MoveFraction = LerpCurve->GetFloatValue(MoveFraction);
			}

			MyActor->SetActorLocation(FMath::Lerp<FVector, float>(StartLocation, TargetLocation, MoveFraction));
		}
	}
	else
	{
		bIsFinished = true;
		EndTask();
	}
}
void ABatteryCollectorGameMode::HandleNewState(EBatteryPlayState NewState)
{
	switch (NewState)
	{
	case EBatteryPlayState::EPlaying:
	{
		for (ASpawnVolume* Volume : SpawnVolumeActors)
		{
			Volume->SetSpawningActive(true);
		}
	}
	break;
	case EBatteryPlayState::EGameOver:
	{
		for (ASpawnVolume* Volume : SpawnVolumeActors)
		{
			Volume->SetSpawningActive(false);
		}
		APlayerController* PlayerController = UGameplayStatics::GetPlayerController(this, 0);
		if (PlayerController)
		{
			PlayerController->SetCinematicMode(true, false, false, true, true);
		}

		ACharacter* MyCharacter = UGameplayStatics::GetPlayerCharacter(this, 0);
		if (MyCharacter)
		{
			MyCharacter->GetMesh()->SetSimulatePhysics(true);
			MyCharacter->GetMovementComponent()->MovementState.bCanJump = false;
		}
	}
	break;
	case EBatteryPlayState::EWon:
	{
		for (ASpawnVolume* Volume : SpawnVolumeActors)
		{
			Volume->SetSpawningActive(false);
		}
	}
	break;
	case EBatteryPlayState::EUnknown:
		break;
	default:
		break;
	}
}
void UAbilityTask_MoveToLocation::OnDestroy(bool AbilityIsEnding)
{
	AActor* MyActor = GetAvatarActor();
	if (MyActor)
	{
		ACharacter* MyCharacter = Cast<ACharacter>(MyActor);
		if (MyCharacter)
		{
			UCharacterMovementComponent* CharMoveComp = Cast<UCharacterMovementComponent>(MyCharacter->GetMovementComponent());
			if (CharMoveComp && CharMoveComp->MovementMode == MOVE_Custom)
			{
				CharMoveComp->SetMovementMode(MOVE_Falling);
			}
		}
	}

	Super::OnDestroy(AbilityIsEnding);
}
void ABatteryCollectorGameMode::HandleNewState(EBatteryPlayState NewState)
{

    
    switch (NewState) {
        case EBatteryPlayState::EPlaying :
            
            // If the game is playing
            //
            // spawn volume active
            for (ASpawnVolume* Volume : SpawnVolumeActors) {
                Volume->SetSpawningActive(true);
            }
            
            break;
        case EBatteryPlayState::EWon :
            
            // if we won the game
            //
            // spawn volume inactive
            for (ASpawnVolume* Volume : SpawnVolumeActors) {
                Volume->SetSpawningActive(false);
            }
            
            
            break;
        case EBatteryPlayState::EGameOver :
        {
            // If we lost
            //
            // spawn volume inactive
            // block player input
            // ragdoll the character
            for (ASpawnVolume* Volume : SpawnVolumeActors) {
                Volume->SetSpawningActive(false);
            }
            
            APlayerController* PlayerController = UGameplayStatics::GetPlayerController(this, 0);
            if(PlayerController)
            {
                PlayerController->SetCinematicMode(true, false, false, true, true);
                
                UE_LOG(LogClass, Log, TEXT("You have set Cinematic Mode"));

            }
            else
            {
                UE_LOG(LogClass, Log, TEXT("Player Controller was invalid!!"));
            }

            // now ragdoll the character
            ACharacter* MyCharacter = UGameplayStatics::GetPlayerCharacter(this, 0);
            if(MyCharacter)
            {
                MyCharacter->GetMesh()->SetSimulatePhysics(true);
                MyCharacter->GetMovementComponent()->MovementState.bCanJump=false;
                
                UE_LOG(LogClass, Log, TEXT("ACharacter jump turned off and Set Simulate Physics on"));
            }else
            {
                UE_LOG(LogClass, Log, TEXT("ACharacter was invalid!! (EGameOver State in HandleNewState"));

            }
        }
            
            break;
            
        default :

            // unknown state - incase some code forgets to call
            //
            // use to help debug
            
            break;
    }
}