using System;
using Aurora.Backend.Models.Media;
using LibVLCSharp.Shared;

namespace Aurora.Backend.Services.PlayerService
{
    public class PlayerService : BaseService<PlayerService>
    {
        private BaseMedia _currentMedia;
        private MediaPlayer _mediaPlayer;
        private LibVLC _libvlc;
        private PlaybackState _state;

        public PlayerService()
        {
            _libvlc = new LibVLC();
            _state = PlaybackState.Stopped;
        }

        /// <summary>
        /// Event handler for changing playback states.
        /// </summary>
        public event PlaybackStateChangedEventHandler PlaybackStateChanged;

        public event MediaChangedEventHandler MediaChanged;

        /// <summary>
        /// The state of playback
        /// </summary>
        /// <value></value>
        public PlaybackState PlaybackState
        {
            get { return _state; }
        }

        /// <summary>
        /// Load media into the media player.
        /// </summary>
        /// <param name="media">Media to load</param>
        public void LoadMedia(BaseMedia media)
        {
            if (_state == PlaybackState.Playing || _state == PlaybackState.Buffering)
            {
                Unload();
            }
            _currentMedia = media;
            _currentMedia.Load();
            var md = new Media(_libvlc, _currentMedia.DataStream);
            _mediaPlayer = new MediaPlayer(md);
            _mediaPlayer.Stopped += OnStopped;
            md.Dispose();

            MediaChanged.Invoke(this, new MediaChangedEventArgs(_currentMedia.Metadata));
        }

        /// <summary>
        /// Play currently loaded media.
        /// </summary>
        public void Play()
        {
            PlaybackState oldState = _state;
            _state = PlaybackState.Playing;
            _mediaPlayer.Play();
            PlaybackStateChanged.Invoke(this, new PlaybackStateChangedEventArgs(oldState, _state));
        }

        /// <summary>
        /// Pause currently loaded media.
        /// </summary>
        public void Pause()
        {
            PlaybackState oldState = _state;
            _state = PlaybackState.Buffering;
            _mediaPlayer.Pause();
            PlaybackStateChanged.Invoke(this, new PlaybackStateChangedEventArgs(oldState, _state));
        }

        /// <summary>
        /// Stop currently loaded media.
        /// </summary>
        public void Stop()
        {
            PlaybackState oldState = _state;
            _state = PlaybackState.Stopped;
            _mediaPlayer.Stop();
            PlaybackStateChanged.Invoke(this, new PlaybackStateChangedEventArgs(oldState, _state));
        }

        public void Enqueue(BaseMedia song)
        {
            throw new NotImplementedException();
        }

        public void Dequeue(BaseMedia song)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Unload currently loaded media.
        /// </summary>
        private void Unload()
        {
            _currentMedia.Unload();
            _mediaPlayer.Media = null;
            _mediaPlayer = null;
        }

        /// <summary>
        /// Event fired when currently loaded media player stops.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void OnStopped(object sender, EventArgs args)
        {
            PlaybackStateChanged.Invoke(this, new PlaybackStateChangedEventArgs(_state, PlaybackState.Stopped));
            _state = PlaybackState.Stopped;
            this.Unload();
        }

    }
}
