text: // Fill out your copyright notice in the Description page of Project Settings.
  
  #include "BattleTank.h"
  #include "TankBarrel.h"
  #include "TankTurret.h"
  #include "Projectile.h"
  #include "TankAimingComponent.h"
  
  
  // Sets default values for this component's properties
  UTankAimingComponent::UTankAimingComponent()
  {
  	// Set this component to be initialized when the game starts, and to be ticked every frame.  You can turn these features
  	// off to improve performance if you don't need them.
  	bWantsBeginPlay = true;
  	PrimaryComponentTick.bCanEverTick = true;
  
  	// ...
  }
  
  
  int UTankAimingComponent::GetRounds() const
  {
  	return RoundsLeft;
  }
  
  void UTankAimingComponent::BeginPlay()
  {
  	LastFireTime = FPlatformTime::Seconds();
  }
  
  void UTankAimingComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction * ThisTickFunction)
  {	
  	if (RoundsLeft <= 0)
  	{
  		FiringState = EFiringState::OutOfAmmo;
  	}
  	else if ((FPlatformTime::Seconds() - LastFireTime) < ReloadTimeInSeconds)
  	{
  		FiringState = EFiringState::Reloading;
  	}
  	else if (IsBarrelMoving())
  	{
  		FiringState = EFiringState::Aiming;
  	}
  	else
  	{
  		FiringState = EFiringState::Locked;
  	}
  }
  
  
  void UTankAimingComponent::AimAt(FVector HitLocation)
  {
  	if (!ensure(Barrel)) { return; }	
  	FVector OutLaunchVelocity;
  	FVector StartLocation = Barrel->GetSocketLocation("Projectile");
  	bool bHaveAimSolution = UGameplayStatics::SuggestProjectileVelocity(this, OutLaunchVelocity, StartLocation, HitLocation, LaunchSpeed, false, 0.0f, 0.0f, ESuggestProjVelocityTraceOption::DoNotTrace);
  	if (bHaveAimSolution)
  	{
  		AimDirection = OutLaunchVelocity.GetSafeNormal();		
  		MoveBarrelTowards(AimDirection);	
  	}
  }
  
  float UTankAimingComponent::GetLaunchSpeed()
  {
  	return LaunchSpeed;
  }
  
  EFiringState UTankAimingComponent::GetFiringState() const
  {
  	return FiringState;
  }
  
  void UTankAimingComponent::Fire()
  {	
  	if ((FiringState == EFiringState::Locked) || (FiringState == EFiringState::Aiming))
  	{
  		if (!ensure(Barrel)) { return; }
  		if (!ensure(ProjectileBlueprint)) { return; }
  		auto Projectile = GetWorld()->SpawnActor<AProjectile>(ProjectileBlueprint, Barrel->GetSocketLocation(FName("Projectile")), Barrel->GetSocketRotation(FName("Projectile")));
  		Projectile->LaunchProjectile(LaunchSpeed);
  		LastFireTime = FPlatformTime::Seconds();
  		RoundsLeft--;
  	}
  }
  
  void UTankAimingComponent::Initialise(UTankBarrel * BarrelToSet, UTankTurret * TurretToSet)
  {
  	Barrel = BarrelToSet;
  	Turret = TurretToSet;
  }
  
  
  void UTankAimingComponent::MoveBarrelTowards(FVector GotAimDirection)
  {
  	if (!ensure(Barrel || Turret)) { return; }
  	auto BarrelRotator = Barrel->GetForwardVector().Rotation();	
  	auto AimAsRotator = GotAimDirection.Rotation();
  	auto DeltaRotator = AimAsRotator - BarrelRotator;
  	Barrel->Elevate(DeltaRotator.Pitch);
  	if (FMath::Abs(DeltaRotator.Yaw) < 180)
  	{ 
  		Turret->Rotate(DeltaRotator.Yaw);
  	}
  	else
  	{
  		Turret->Rotate(-DeltaRotator.Yaw);
  	}
  }
  
  
  bool UTankAimingComponent::IsBarrelMoving()
  {
  	if (!ensure(Barrel)) { return false; }
  	return !Barrel->GetForwardVector().Equals(AimDirection, 0.01f);
  }
  