#pragma once

#include "ehs/EHS.h"
#include "ehs/Str.h"
#include "ehs/Array.h"
#include "ehs/io/socket/SSL.h"

namespace ehs
{
	enum class SpotifyState
	{
		TRACK,
		CONTEXT,
		OFF
	};

	struct Track
	{
		Array<Str_8> artists;
		Str_8 name;
		Str_8 id;
	};

	class EHS_LIB_IO Spotify final
	{
	private:
		SSL client;
		Str_8 clientId;
		Str_8 secret;
		Str_8 redURI;
		Array<Str_8> scopes;
		bool forceVerify;
		Str_8 token;
		Str_8 rToken;

	public:
		static const Str_8 trackUriPrefix;

		virtual ~Spotify();

		Spotify();

		Spotify(Str_8 clientId, Str_8 secret, Str_8 redURI, Array<Str_8> scopes, bool forceVerify);

		bool Authorize();

		/// Sets the volume for a device.
		/// @param [in] level The percentage to set the volume to.
		/// @returns The response code.
		UInt_32 SetVolume(UInt_8 level);

		/// Resume playback for a device.
		/// @returns The response code.
		UInt_32 Play();

		/// Pauses playback for a device.
		/// @returns The response code.
		UInt_32 Pause();

		/// Repeats playback for a device.
		/// @param [in] status The status to set it to.
		/// @returns The response code.
		UInt_32 SetRepeat(SpotifyState state);

		/// Shuffles playback for a device.
		/// @param [in] state The state to set shuffle to.
		/// @returns The response code.
		UInt_32 SetShuffle(bool state);

		UInt_32 SearchTrack(Vector<Str_8>& artists, Str_8& id, Str_8& name);

		UInt_32 GetPlayingTrack(Vector<Str_8>& artists, Str_8& id, Str_8& name);

		UInt_32 GetQueue(Array<Track>& tracks);

		/// Adds a track to the queue for a device.
		/// @param [in] uri The track id to add.
		/// @returns The response code.
		UInt_32 QueueTrack(const Str_8& id);

		UInt_32 AddTracks(const Str_8& playlistId, const Array<Str_8>& trackIds, const UInt_32 pos = 0);

		UInt_32 AddTrack(const Str_8& playlistId, const Str_8& trackId, const UInt_32 pos = 0);

		/// Skips to the next track.
		/// @returns The response code.
		UInt_32 Skip();

		/// Skips to the previous track.
		/// @returns The response code.
		UInt_32 Previous();

		/// Seeks to a position of the currently playing track in milliseconds.
		/// @param [in] pos The position in milliseconds to seek to.
		/// @returns The response code.
		UInt_32 Seek(UInt_32 pos);

		Str_8 GetClientId() const;

		Str_8 GetSecret() const;

		Str_8 GetRedURI() const;

		bool IsVerificationForced() const;

		bool IsActive() const;

	private:
		void StartConnection();

		bool ReAuthorize();
	};
}