/*
* Neural Tanks is a game created by Eddie O'Hagan that leverages Neural Networking
* to use for AI. This was created in Unreal Engine 4 which is developed by Epic Games.
* (Copyright Epic Games, Inc. All Rights Reserved.)
*
* Smart Tanks was originally developed by Mat Buckland in 2002 as an example
* on how Neural Networking can be used to train a set of minesweepers
* to collect mines. I (Eddie O'Hagan) updated this project in 2024 to use more
* Object Oriented Programming and modern practices. To see the original tutorial;
* visit <see href="http://www.ai-junkie.com/ann/evolved/nnt1.html">Neural Networking Tutorial</see>
* and <see href="http://www.ai-junkie.com/ga/intro/gat1.html">Genetic Algorithm Tutorial</see>
*/
#include "Boombox.h"

/// <summary>
/// Default constructor for the boombox.
/// </summary>
UBoombox::UBoombox() : Super()
{
	myIsOn = false;
	myVolume = 1.0f;
	myCurrentStationIndex = 0;
	myCurrentStation = NULL;
}

/// <summary>
/// Creates the radio stations from the blueprints and adds them to the myStations collection.
/// </summary>
void UBoombox::Initialize()
{
	URadioStation* currStation;

	myStations.Empty();

	//Create and initialize the station objects from the blueprints.
	for (int index = 0; index < myStationBlueprints.Num(); index++)
	{
		currStation = NewObject<URadioStation>(GetWorld(), myStationBlueprints[index]);
		currStation->Initialize(myVolume, this);

		myStations.Add(currStation);
	}
}

/// <summary>
/// Turns on the boombox and starts by playing a random station.
/// </summary>
void UBoombox::TurnOn()
{
	if (myIsOn == false)
	{
		//Pick a random station to start with.
		myCurrentStationIndex = FMath::RandRange(0, myStations.Num() - 1);
		myCurrentStation = myStations[myCurrentStationIndex];

		myIsOn = true;
		myCurrentStation->StartPlayingStation();
	}
}

/// <summary>
/// Turns off the boombox and stops playing music.
/// </summary>
void UBoombox::TurnOff()
{
	if (myIsOn == true)
	{
		myIsOn = false;
		myCurrentStation->StopPlayingStation();
	}
}

/// <summary>
/// Turns the boombox on if it is off, and turns the boombox off 
/// if it is on.
/// </summary>
void UBoombox::ToggleOnOff()
{
	//If radio is on, turn it off. If radio is off, turn it on.
	if (myIsOn == true)
	{
		TurnOff();
	}
	else
	{
		TurnOn();
	}
}

/// <summary>
/// Increments the station index and starts playing the next station
/// in the radio stations collection.
/// </summary>
void UBoombox::TuneToNextStation()
{
	if (myIsOn == true)
	{
		//Stop the current station music.
		myCurrentStation->StopPlayingStation();

		//Increment and wrap around to 0 if we are at the end.
		myCurrentStationIndex = (myCurrentStationIndex + 1) % myStations.Num();
		myCurrentStation = myStations[myCurrentStationIndex];

		//Play the next/updated station music.
		myCurrentStation->StartPlayingStation();
	}
}

/// <summary>
/// Decrements the station index and starts playing the previous 
/// station in the radio stations collection.
/// </summary>
void UBoombox::TuneToPreviousStation()
{
	if (myIsOn == true)
	{
		//Stop the current station music.
		myCurrentStation->StopPlayingStation();

		//Decrement and wrap around to myStations.Num() - 1 if we are at the beginning.
		myCurrentStationIndex--;
		if (myCurrentStationIndex < 0)
		{
			myCurrentStationIndex = myStations.Num() - 1;
		}
		myCurrentStation = myStations[myCurrentStationIndex];

		//Play the next/updated station music.
		myCurrentStation->StartPlayingStation();
	}
}

/// <summary>
/// Updates the volume to myVolume for all of the radio stations 
/// in the collection.
/// </summary>
void UBoombox::UpdateVolume()
{
	//Update the volume to be the same as the boombox global volume across all stations.
	for (int index = 0; index < myStations.Num(); index++)
	{
		myStations[index]->UpdateVolume(myVolume);
	}
}

/// <summary>
/// Increments myVolume by 1.0 for all stations (including the one currently playing).
/// </summary>
void UBoombox::IncreaseVolume()
{
	myVolume = FMath::Clamp(myVolume + 1, 1.0f, (float)MAX_flt);

	UpdateVolume();
}

/// <summary>
/// Decrements myVolume by 1.0 for all stations (including the one currently playing).
/// </summary>
void UBoombox::DecreaseVolume()
{
	myVolume = FMath::Clamp(myVolume - 1, 1.0f, (float)MAX_flt);
	
	UpdateVolume();
}

/// <summary>
/// Returns the current station being played.
/// </summary>
/// <returns>The currently selected station being played.</returns>
URadioStation* UBoombox::GetCurrentStation() const
{
	return myCurrentStation;
}