#include "Service.h"
#include <algorithm>
#include "FilePlaylist.h"
#include "RepositoryExceptions.h"

using namespace std;

void Service::addSongToRepository(const std::string& artist, const std::string& title, double minutes, double seconds, const std::string& source)
{
	Song s{ artist, title, Duration{ minutes, seconds }, source };
	this->validator.validate(s);
	this->repo.addSong(s);
	
	undoActions.push_back(std::make_unique<AddAction>(this->repo, s));
	redoActions.clear();

}

void Service::removeSongFromRepository(const std::string & artist, const std::string & title)
{
	Song s = this->repo.findByArtistAndTitle(artist, title);
	this->repo.removeSong(s);

	undoActions.push_back(std::make_unique<RemoveAction>(this->repo, s));
	redoActions.clear();
}

void Service::addSongToPlaylist(const Song& song)
{
	if (this->playList == nullptr)
		return;
	this->playList->add(song);
}

void Service::addAllSongsByArtistToPlaylist(const std::string& artist)
{
	vector<Song> songs = this->repo.getSongs();
	int nSongs = static_cast<int>(count_if(songs.begin(), songs.end(),
		[artist](const Song& s)
		{
			return s.getArtist() == artist;
		}));

	vector<Song> songsByArtist(nSongs);
	copy_if(songs.begin(), songs.end(), songsByArtist.begin(),
		[artist](const Song& s)
		{
			return s.getArtist() == artist;
		});

	for (auto s : songsByArtist)
		this->playList->add(s);
}

void Service::startPlaylist()
{
	if (this->playList == nullptr)
		return;
	this->playList->play();
}

void Service::nextSongPlaylist()
{
	if (this->playList == nullptr)
		return;
	this->playList->next();
}

void Service::savePlaylist(const std::string& filename)
{
	if (this->playList == nullptr)
		return;

	this->playList->setFilename(filename);
	this->playList->writeToFile();
}

void Service::openPlaylist() const
{
	if (this->playList == nullptr)
		return;

	this->playList->displayPlaylist();
}

void Service::undo()
{
	if (undoActions.empty())
		throw RepositoryException("No more undos!\n");
	undoActions.back()->executeUndo();
	redoActions.push_back(std::move(undoActions.back()));
	undoActions.pop_back();
}

void Service::redo()
{
	if (redoActions.empty())
		throw RepositoryException("No more redos!\n");
	redoActions.back()->executeRedo();
	undoActions.push_back(std::move(redoActions.back()));
	redoActions.pop_back();
}

