using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Aurora.Proto.General;
using Aurora.Proto.Playback;
using Aurora.Proto.Sync;

namespace Aurora.Models.Media
{
    public class RemoteAudio : BaseMedia
    {
        private RemotePlaybackService.RemotePlaybackServiceClient _remotePlaybackClient;
        private RemoteSyncService.RemoteSyncServiceClient _remoteSyncClient;
        private CancellationTokenSource _cancellationTokenSource;

        #region Constructor
        public RemoteAudio(string id,
            bool fromHost,
            AudioMetadata metadata,
            RemotePlaybackService.RemotePlaybackServiceClient playbackClient,
            RemoteSyncService.RemoteSyncServiceClient syncClient)
        {
            this.Id = id;
            this._remotePlaybackClient = playbackClient;
            this._remoteSyncClient = syncClient;
            this.Metadata = metadata;
            this.FromHost = fromHost;

            _cancellationTokenSource = new CancellationTokenSource();
        }

        #endregion Constructor

        #region Properties

        public override BaseMetadata Metadata { get; protected set; }

        public override MediaTypeEnum MediaType
        {
            get { return MediaTypeEnum.Audio; }
        }

        public RemoteSyncService.RemoteSyncServiceClient RemoteSyncClient
        {
            get
            {
                return _remoteSyncClient;
            }
        }

        public bool FromHost { get; private set; }
        #endregion Properties

        /// <summary>
        /// Override load method.
        /// </summary>
        public override async Task Load()
        {
            this.DataStream = new MemoryStream();
            using (var call = _remotePlaybackClient.GetSongStream(new SongRequest() { Id = this.Id }))
            {
                try
                {
                    while (await call.ResponseStream.MoveNext(_cancellationTokenSource.Token))
                    {
                        Chunk chunk = call.ResponseStream.Current;
                        byte[] buffer = chunk.Content.ToByteArray();

                        await this.DataStream.WriteAsync(buffer, 0, buffer.Length);
                    }
                    Console.WriteLine("Done receiving stream");
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Exception caught while loading remote audio:" + ex.Message);
                }
            }
            await base.Load();
        }

        /// <summary>
        /// Override unload method
        /// </summary>
        public override void Unload()
        {
            // if (!_cancellationTokenSource.IsCancellationRequested)
            // {
            //     _cancellationTokenSource.Cancel();

            //     //Wait for cancellation
            //     WaitHandle.WaitAny(new[] { _cancellationTokenSource.Token.WaitHandle });
            // }
            base.Unload();
        }
    }
}