/*
* 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 "RadioStation.h"
#include "Boombox.h"
#include <Kismet/GameplayStatics.h>
#include <NeuralTanks/Utils/NeuralTanksUtils.h>

/// <summary>
/// Default constructor for the Radio Station.
/// </summary>
URadioStation::URadioStation() : Super()
{
	myCurrentSong = NULL;
	myStationLogo = NULL;
}

/// <summary>
/// Initializes this radio station by setting it's parent and setting the volume
/// for all the songs in this station.
/// </summary>
/// <param name="boomboxVolume">The volume set by the player for the Boombox.</param>
/// <param name="theOwningBoombox">The owning Boombox for this Radio Station.</param>
void URadioStation::Initialize(const float boomboxVolume, UBoombox* theOwningBoombox)
{
	myOwningBoombox = theOwningBoombox;
	UpdateVolume(boomboxVolume);
}

/// <summary>
/// Starts the next song when one finishes.
/// </summary>
/// <param name="thePlayState">The state of the song.</param>
void URadioStation::OnPlayStateChanged(EAudioComponentPlayState thePlayState)
{
	if (myCurrentSong != NULL)
	{
		//Current song stopped so play the next song.
		if (thePlayState == EAudioComponentPlayState::Stopped)
		{
			StartPlayingStation();
			myOwningBoombox->UpdateBoomboxUI();
		}
	}
}

/// <summary>
/// Randomly chooses a song from the collection and starts playing it.
/// Also registers the handler for OnPlayStateChanged.
/// </summary>
void URadioStation::StartPlayingStation()
{
	//Pick a song at random from the map by picking a random key.
	int randomSongIndex = FMath::RandRange(0, mySongs.Num() - 1);
	TArray<FString> songNames;

	mySongs.GetKeys(songNames);
	myCurrentSongName = songNames[randomSongIndex];

	//Play the selected song.
	myCurrentSong = UGameplayStatics::CreateSound2D(GetWorld(), mySongs[myCurrentSongName]);
	myCurrentSong->Play();

	//Register a delegate with the song so we know when it finishes (playing=0 stopped=1).
	myCurrentSong->OnAudioPlayStateChanged.AddUniqueDynamic(this, &URadioStation::OnPlayStateChanged);
}

/// <summary>
/// Stops playing the current song and unregisters the handler 
/// for OnPlayStateChanged.
/// </summary>
void URadioStation::StopPlayingStation()
{
	if (myCurrentSong != NULL)
	{
		myCurrentSong->OnAudioPlayStateChanged.Clear();
		myCurrentSong->Stop();
	}
}

/// <summary>
/// Sets the volume for all of the songs in the collection with
/// the provided boomboxVolume.
/// </summary>
/// <param name="boomboxVolume">The volume to use for all the songs in this station.</param>
void URadioStation::UpdateVolume(const float boomboxVolume)
{
	//Set the volume of all the songs on the station to the provided volume of the boombox.
	for (TTuple<FString, USoundWave*> currSong : mySongs)
	{
		currSong.Value->Volume = boomboxVolume;
	}
}

/// <summary>
/// Returns the name of the station (typically describes the genre).
/// </summary>
/// <returns>The name of the station.</returns>
FText URadioStation::GetStationName() const
{
	return myStationName;
}

/// <summary>
/// Returns the currently playing song name.
/// </summary>
/// <returns>The name of song currently playing.</returns>
FString URadioStation::GetCurrentSongDetails() const
{
	return myCurrentSongName;
}

/// <summary>
/// Returns the image used for this station in the Boombox GUI.
/// </summary>
/// <returns>The image used for this station in the Boombox GUI.</returns>
UTexture2D* URadioStation::GetStationLogo() const
{
	return myStationLogo;
}