using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Threading;
using Jellyfin.Api.Constants;
using Jellyfin.Api.Helpers;
using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Session;
using MediaBrowser.Controller.SyncPlay;
using MediaBrowser.Model.SyncPlay;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace Jellyfin.Api.Controllers
{
    /// 
    /// The sync play controller.
    /// 
    [Authorize(Policy = Policies.DefaultAuthorization)]
    public class SyncPlayController : BaseJellyfinApiController
    {
        private readonly ISessionManager _sessionManager;
        private readonly IAuthorizationContext _authorizationContext;
        private readonly ISyncPlayManager _syncPlayManager;
        /// 
        /// Initializes a new instance of the  class.
        /// 
        /// Instance of the  interface.
        /// Instance of the  interface.
        /// Instance of the  interface.
        public SyncPlayController(
            ISessionManager sessionManager,
            IAuthorizationContext authorizationContext,
            ISyncPlayManager syncPlayManager)
        {
            _sessionManager = sessionManager;
            _authorizationContext = authorizationContext;
            _syncPlayManager = syncPlayManager;
        }
        /// 
        /// Create a new SyncPlay group.
        /// 
        /// New group created.
        /// A  indicating success.
        [HttpPost("New")]
        [ProducesResponseType(StatusCodes.Status204NoContent)]
        public ActionResult SyncPlayCreateGroup()
        {
            var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request);
            _syncPlayManager.NewGroup(currentSession, CancellationToken.None);
            return NoContent();
        }
        /// 
        /// Join an existing SyncPlay group.
        /// 
        /// The sync play group id.
        /// Group join successful.
        /// A  indicating success.
        [HttpPost("Join")]
        [ProducesResponseType(StatusCodes.Status204NoContent)]
        public ActionResult SyncPlayJoinGroup([FromQuery, Required] Guid groupId)
        {
            var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request);
            var joinRequest = new JoinGroupRequest()
            {
                GroupId = groupId
            };
            _syncPlayManager.JoinGroup(currentSession, groupId, joinRequest, CancellationToken.None);
            return NoContent();
        }
        /// 
        /// Leave the joined SyncPlay group.
        /// 
        /// Group leave successful.
        /// A  indicating success.
        [HttpPost("Leave")]
        [ProducesResponseType(StatusCodes.Status204NoContent)]
        public ActionResult SyncPlayLeaveGroup()
        {
            var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request);
            _syncPlayManager.LeaveGroup(currentSession, CancellationToken.None);
            return NoContent();
        }
        /// 
        /// Gets all SyncPlay groups.
        /// 
        /// Optional. Filter by item id.
        /// Groups returned.
        /// An  containing the available SyncPlay groups.
        [HttpGet("List")]
        [ProducesResponseType(StatusCodes.Status200OK)]
        public ActionResult> SyncPlayGetGroups([FromQuery] Guid? filterItemId)
        {
            var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request);
            return Ok(_syncPlayManager.ListGroups(currentSession, filterItemId.HasValue ? filterItemId.Value : Guid.Empty));
        }
        /// 
        /// Request play in SyncPlay group.
        /// 
        /// Play request sent to all group members.
        /// A  indicating success.
        [HttpPost("Play")]
        [ProducesResponseType(StatusCodes.Status204NoContent)]
        public ActionResult SyncPlayPlay()
        {
            var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request);
            var syncPlayRequest = new PlaybackRequest()
            {
                Type = PlaybackRequestType.Play
            };
            _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
            return NoContent();
        }
        /// 
        /// Request pause in SyncPlay group.
        /// 
        /// Pause request sent to all group members.
        /// A  indicating success.
        [HttpPost("Pause")]
        [ProducesResponseType(StatusCodes.Status204NoContent)]
        public ActionResult SyncPlayPause()
        {
            var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request);
            var syncPlayRequest = new PlaybackRequest()
            {
                Type = PlaybackRequestType.Pause
            };
            _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
            return NoContent();
        }
        /// 
        /// Request seek in SyncPlay group.
        /// 
        /// The playback position in ticks.
        /// Seek request sent to all group members.
        /// A  indicating success.
        [HttpPost("Seek")]
        [ProducesResponseType(StatusCodes.Status204NoContent)]
        public ActionResult SyncPlaySeek([FromQuery] long positionTicks)
        {
            var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request);
            var syncPlayRequest = new PlaybackRequest()
            {
                Type = PlaybackRequestType.Seek,
                PositionTicks = positionTicks
            };
            _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
            return NoContent();
        }
        /// 
        /// Request group wait in SyncPlay group while buffering.
        /// 
        /// When the request has been made by the client.
        /// The playback position in ticks.
        /// Whether the buffering is done.
        /// Buffering request sent to all group members.
        /// A  indicating success.
        [HttpPost("Buffering")]
        [ProducesResponseType(StatusCodes.Status204NoContent)]
        public ActionResult SyncPlayBuffering([FromQuery] DateTime when, [FromQuery] long positionTicks, [FromQuery] bool bufferingDone)
        {
            var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request);
            var syncPlayRequest = new PlaybackRequest()
            {
                Type = bufferingDone ? PlaybackRequestType.Ready : PlaybackRequestType.Buffer,
                When = when,
                PositionTicks = positionTicks
            };
            _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
            return NoContent();
        }
        /// 
        /// Update session ping.
        /// 
        /// The ping.
        /// Ping updated.
        /// A  indicating success.
        [HttpPost("Ping")]
        [ProducesResponseType(StatusCodes.Status204NoContent)]
        public ActionResult SyncPlayPing([FromQuery] double ping)
        {
            var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request);
            var syncPlayRequest = new PlaybackRequest()
            {
                Type = PlaybackRequestType.Ping,
                Ping = Convert.ToInt64(ping)
            };
            _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
            return NoContent();
        }
    }
}