using System;

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

 

namespace Jukebox

{

    ////////////////////////////////////////////////////////////////////////////////

    /// <summary>

    /// Interface for getting basic stats about the currently playing track. The

    /// IPlayCounter should be obtained by getting the PlayCounter property from the

    /// currently playing ITrack, and then discarded after use, as it can become out

    /// of-date when the playlist changes.

    /// </summary>

    public interface IPlayCounter

    {

        /// <summary>

        /// Gets the duration of the currently playing track in Seconds

        /// </summary>

        float TrackDuration { get; }

 

        /// <summary>

        /// Gets the played duration of the currently playing track in Seconds

        /// </summary>

        float PlayedDuration { get; }

    }

 

    ////////////////////////////////////////////////////////////////////////////////

    /// <summary>

    /// Interface exposing information about tracks sourced from Jukebox

    /// </summary>

    public interface ITrack

    {

        /// <summary>

        /// Gets the name of the track

        /// </summary>

        string Name { get; }

 

        /// <summary>

        /// Gets the name of the artist who performed the track

        /// </summary>

        string Artist { get; }

 

        /// <summary>

        /// Gets a URL to find out more about the artist who performed the track

        /// </summary>

        string ArtistUrl { get; }

 

        /// <summary>

        /// Gets the name of the album on which the track was released

        /// </summary>

        string Album { get; }

 

        /// <summary>

        /// Gets the genre for the track

        /// </summary>

        string Genre { get; }

 

        /// <summary>

        /// Gets any additional text tags that the track has been annotated with

        /// </summary>

        string Tags { get; }

 

        /// <summary>

        /// Gets a URL for an image to represent the track

        /// </summary>

        string TrackImageUrl { get; }

 

        /// <summary>

        /// Returns the audio clip containing the track

        /// </summary>

        AudioClip AudioClip { get; }

 

        /// <summary>

        /// Returns true if the audio clip is ready to play

        /// </summary>

        bool IsReady { get; }

 

        /// <summary>

        /// Returns an IPlayCounter reference to get dynamic playback information

        /// about the current track.

        /// NOTE: this will only return valid information whilst the current track

        /// is playing. It should be re-requested for subsequent tracks

        /// </summary>

        IPlayCounter PlayCounter { get; }

    }

 

    /// <summary>

    /// Event delegate that can be registered to events from IPlaylist or IControl

    /// to be notified when the active track changes

    /// </summary>

    public delegate void NewTrackEventHandler(object sender, ITrack track);

 

    ////////////////////////////////////////////////////////////////////////////////

    /// <summary>

    /// Interface implemented by IPlaylist and IControl. Both of these methods

    /// should be called from the corresponding methods in the parent MonoBehaviour

    /// class to correctly initialize and update the extension objects.

    /// </summary>

    public interface IBehaviourExtension

    {

        /// <summary>

        /// Call Start within the parent MonoBehaviour script’s Start method, to

        /// allow the component to correctly initialize itself.

        /// </summary>

        /// <param name=”parent“>

        /// The parent script that nominally owns and uses this component

        /// </param>

        void Start(MonoBehaviour parent);

 

        /// <summary>

        /// Call Update within the parent MonoBehaviour script’s Update method, to

        /// allow the component to update itself.

        /// </summary>

        void Update();

    }

 

    ////////////////////////////////////////////////////////////////////////////////

    /// <summary>

    /// Interface for accessing and controlling the current track being played by

    /// the Jukebox system. This interface is inherited by both IPlaylist and

    /// IControl. When multiple playlists are present in a game scene, then the

    /// IControl-inherited version of this interface should be used by the wider

    /// game code, as it co-ordinates playback between each of the individual

    /// playlists. If just a single playlist is declared, then that playlist may be

    /// used directly.

    /// </summary>

    public interface IPlaybackControl : IBehaviourExtension

    {

        /// <summary>

        /// Get the currently playing track controlled by this interface.

        /// </summary>

        ITrack CurrentTrack { get; }

 

        /// <summary>

        /// Start playback of the currently selected track.

        /// </summary>

        void StartPlayback();

 

        /// <summary>

        /// Pause the currently playing track.

        /// </summary>

        void PausePlayback();

 

        /// <summary>

        /// Skip the currently playing track and start playing the next track in

        /// the playlist.

        /// </summary>

        void SkipCurrentTrack();

 

        /// <summary>

        /// Send feedback to Jukebox that the user likes the currently

        /// playing track.

        /// </summary>

        void LikeCurrentTrack();

 

        /// <summary>

        /// Send feedback to Jukebox that the user dislikes the currently playing

        /// track.

        /// Note: this keeps the track playing; SkipCurrentTrack must be called

        /// to actually skip tracks.

        /// </summary>

        void DislikeCurrentTrack();

 

        /// <summary>

        /// The OnNewTrack event fires whenever a new track associated with this

        /// interface starts playing.

        /// </summary>

        event NewTrackEventHandler OnNewTrack;

    }

 

    ////////////////////////////////////////////////////////////////////////////////

    /// <summary>

    /// Interface to access a Jukebox playlist. If a scene contains just a single

    /// playlist then this interface may be used to interact with the transport. If

    /// multiple playlists are being used then the IControl interface should be used

    /// instead to control and query the active playlist.

    /// </summary>

    public interface IPlaylist : IPlaybackControl

    {

    }

 

    /// <summary>

    /// Interface to manage and query the active playlist in a multi-playlist scene.

    /// Setting the ‘CurrentPlaylist’ property allows the Jukebox component to

    /// correctly switch between multiple IPlaylist objects

    /// </summary>

    public interface IControl : IPlaybackControl

    {

        /// <summary>

        /// Gets and Sets the current playlist. Use of the IControl.CurrentPlaylist

        /// set method is the recommended way to switch between active playlists.

        /// Assigning a playlist in this manner will automatically start and stop

        /// playback across playlists correctly; and ensure the correct metadata is

        /// exposed via the IControl’s IPlaybackControl methods.

        /// </summary>

        IPlaylist CurrentPlaylist { get; set; }

    }

 

    ////////////////////////////////////////////////////////////////////////////////

    /// <summary>

    /// Factory class for instantiating instances of the IControl and IPlaylist

    /// classes

    /// </summary>

    public class Factory

    {

        /// <summary>

        /// Factory method for Jukebox.IControl

        /// </summary>

        /// <returns>

        /// a reference to an instance of the global Jukebox.IControl object

        /// </returns>

        public static IControl GetControl()

        {

            return JukeboxImpl.Factory.GetControl();

        }

 

        /// <summary>

        /// Factory method for Jukebox.IPlaylist

        /// </summary>

        /// <param name=”source“>

        /// The AudioSource object that will receive streamed audio data when this

        /// playlist is playing

        /// </param>

        /// <param name=”playlistToken“>

        /// The textual playlist token generated for this playlist on

        /// https://www.jukeboxaudio.co

        /// </param>

        /// <param name=”shufflePlay“>

        /// If set to true, the order of playback of playlist tracks is randomised

        /// </param>

        /// <param name=”autoStart“>

        /// If set to true, this playlist will start playing as soon as it is loaded.

        /// </param>

        /// <remarks>

        /// Only one Playlist object in a scene should be initialized with

        /// autoStart = true, so only one track begins playing

        /// </remarks>

        /// <returns>an instance of a Jukebox.IPlaylist object</returns>

        public static IPlaylist CreatePlaylist(AudioSource source,

                                               string playlistToken,

                                               bool shufflePlay,

                                               bool autoStart)

        {

            return JukeboxImpl.Factory.CreatePlaylist(source, playlistToken, shufflePlay, autoStart);

        }

    }

}