using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Threading;
using Jellyfin.Api.Constants;
using Jellyfin.Api.Helpers;
using Jellyfin.Api.Models.SyncPlayDtos;
using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Session;
using MediaBrowser.Controller.SyncPlay;
using MediaBrowser.Controller.SyncPlay.PlaybackRequests;
using MediaBrowser.Controller.SyncPlay.Requests;
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.SyncPlayHasAccess)]
    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.
        /// 
        /// The settings of the new group.
        /// New group created.
        /// A  indicating success.
        [HttpPost("New")]
        [ProducesResponseType(StatusCodes.Status204NoContent)]
        [Authorize(Policy = Policies.SyncPlayCreateGroup)]
        public ActionResult SyncPlayCreateGroup(
            [FromBody, Required] NewGroupRequestDto requestData)
        {
            var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request);
            var syncPlayRequest = new NewGroupRequest(requestData.GroupName);
            _syncPlayManager.NewGroup(currentSession, syncPlayRequest, CancellationToken.None);
            return NoContent();
        }
        /// 
        /// Join an existing SyncPlay group.
        /// 
        /// The group to join.
        /// Group join successful.
        /// A  indicating success.
        [HttpPost("Join")]
        [ProducesResponseType(StatusCodes.Status204NoContent)]
        [Authorize(Policy = Policies.SyncPlayJoinGroup)]
        public ActionResult SyncPlayJoinGroup(
            [FromBody, Required] JoinGroupRequestDto requestData)
        {
            var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request);
            var syncPlayRequest = new JoinGroupRequest(requestData.GroupId);
            _syncPlayManager.JoinGroup(currentSession, syncPlayRequest, CancellationToken.None);
            return NoContent();
        }
        /// 
        /// Leave the joined SyncPlay group.
        /// 
        /// Group leave successful.
        /// A  indicating success.
        [HttpPost("Leave")]
        [ProducesResponseType(StatusCodes.Status204NoContent)]
        [Authorize(Policy = Policies.SyncPlayIsInGroup)]
        public ActionResult SyncPlayLeaveGroup()
        {
            var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request);
            var syncPlayRequest = new LeaveGroupRequest();
            _syncPlayManager.LeaveGroup(currentSession, syncPlayRequest, CancellationToken.None);
            return NoContent();
        }
        /// 
        /// Gets all SyncPlay groups.
        /// 
        /// Groups returned.
        /// An  containing the available SyncPlay groups.
        [HttpGet("List")]
        [ProducesResponseType(StatusCodes.Status200OK)]
        [Authorize(Policy = Policies.SyncPlayJoinGroup)]
        public ActionResult> SyncPlayGetGroups()
        {
            var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request);
            var syncPlayRequest = new ListGroupsRequest();
            return Ok(_syncPlayManager.ListGroups(currentSession, syncPlayRequest));
        }
        /// 
        /// Request to set new playlist in SyncPlay group.
        /// 
        /// The new playlist to play in the group.
        /// Queue update sent to all group members.
        /// A  indicating success.
        [HttpPost("SetNewQueue")]
        [ProducesResponseType(StatusCodes.Status204NoContent)]
        [Authorize(Policy = Policies.SyncPlayIsInGroup)]
        public ActionResult SyncPlaySetNewQueue(
            [FromBody, Required] PlayRequestDto requestData)
        {
            var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request);
            var syncPlayRequest = new PlayGroupRequest(
                requestData.PlayingQueue,
                requestData.PlayingItemPosition,
                requestData.StartPositionTicks);
            _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
            return NoContent();
        }
        /// 
        /// Request to change playlist item in SyncPlay group.
        /// 
        /// The new item to play.
        /// Queue update sent to all group members.
        /// A  indicating success.
        [HttpPost("SetPlaylistItem")]
        [ProducesResponseType(StatusCodes.Status204NoContent)]
        [Authorize(Policy = Policies.SyncPlayIsInGroup)]
        public ActionResult SyncPlaySetPlaylistItem(
            [FromBody, Required] SetPlaylistItemRequestDto requestData)
        {
            var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request);
            var syncPlayRequest = new SetPlaylistItemGroupRequest(requestData.PlaylistItemId);
            _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
            return NoContent();
        }
        /// 
        /// Request to remove items from the playlist in SyncPlay group.
        /// 
        /// The items to remove.
        /// Queue update sent to all group members.
        /// A  indicating success.
        [HttpPost("RemoveFromPlaylist")]
        [ProducesResponseType(StatusCodes.Status204NoContent)]
        [Authorize(Policy = Policies.SyncPlayIsInGroup)]
        public ActionResult SyncPlayRemoveFromPlaylist(
            [FromBody, Required] RemoveFromPlaylistRequestDto requestData)
        {
            var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request);
            var syncPlayRequest = new RemoveFromPlaylistGroupRequest(requestData.PlaylistItemIds);
            _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
            return NoContent();
        }
        /// 
        /// Request to move an item in the playlist in SyncPlay group.
        /// 
        /// The new position for the item.
        /// Queue update sent to all group members.
        /// A  indicating success.
        [HttpPost("MovePlaylistItem")]
        [ProducesResponseType(StatusCodes.Status204NoContent)]
        [Authorize(Policy = Policies.SyncPlayIsInGroup)]
        public ActionResult SyncPlayMovePlaylistItem(
            [FromBody, Required] MovePlaylistItemRequestDto requestData)
        {
            var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request);
            var syncPlayRequest = new MovePlaylistItemGroupRequest(requestData.PlaylistItemId, requestData.NewIndex);
            _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
            return NoContent();
        }
        /// 
        /// Request to queue items to the playlist of a SyncPlay group.
        /// 
        /// The items to add.
        /// Queue update sent to all group members.
        /// A  indicating success.
        [HttpPost("Queue")]
        [ProducesResponseType(StatusCodes.Status204NoContent)]
        [Authorize(Policy = Policies.SyncPlayIsInGroup)]
        public ActionResult SyncPlayQueue(
            [FromBody, Required] QueueRequestDto requestData)
        {
            var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request);
            var syncPlayRequest = new QueueGroupRequest(requestData.ItemIds, requestData.Mode);
            _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
            return NoContent();
        }
        /// 
        /// Request unpause in SyncPlay group.
        /// 
        /// Unpause update sent to all group members.
        /// A  indicating success.
        [HttpPost("Unpause")]
        [ProducesResponseType(StatusCodes.Status204NoContent)]
        [Authorize(Policy = Policies.SyncPlayIsInGroup)]
        public ActionResult SyncPlayUnpause()
        {
            var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request);
            var syncPlayRequest = new UnpauseGroupRequest();
            _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
            return NoContent();
        }
        /// 
        /// Request pause in SyncPlay group.
        /// 
        /// Pause update sent to all group members.
        /// A  indicating success.
        [HttpPost("Pause")]
        [ProducesResponseType(StatusCodes.Status204NoContent)]
        [Authorize(Policy = Policies.SyncPlayIsInGroup)]
        public ActionResult SyncPlayPause()
        {
            var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request);
            var syncPlayRequest = new PauseGroupRequest();
            _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
            return NoContent();
        }
        /// 
        /// Request stop in SyncPlay group.
        /// 
        /// Stop update sent to all group members.
        /// A  indicating success.
        [HttpPost("Stop")]
        [ProducesResponseType(StatusCodes.Status204NoContent)]
        [Authorize(Policy = Policies.SyncPlayIsInGroup)]
        public ActionResult SyncPlayStop()
        {
            var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request);
            var syncPlayRequest = new StopGroupRequest();
            _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
            return NoContent();
        }
        /// 
        /// Request seek in SyncPlay group.
        /// 
        /// The new playback position.
        /// Seek update sent to all group members.
        /// A  indicating success.
        [HttpPost("Seek")]
        [ProducesResponseType(StatusCodes.Status204NoContent)]
        [Authorize(Policy = Policies.SyncPlayIsInGroup)]
        public ActionResult SyncPlaySeek(
            [FromBody, Required] SeekRequestDto requestData)
        {
            var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request);
            var syncPlayRequest = new SeekGroupRequest(requestData.PositionTicks);
            _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
            return NoContent();
        }
        /// 
        /// Notify SyncPlay group that member is buffering.
        /// 
        /// The player status.
        /// Group state update sent to all group members.
        /// A  indicating success.
        [HttpPost("Buffering")]
        [ProducesResponseType(StatusCodes.Status204NoContent)]
        [Authorize(Policy = Policies.SyncPlayIsInGroup)]
        public ActionResult SyncPlayBuffering(
            [FromBody, Required] BufferRequestDto requestData)
        {
            var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request);
            var syncPlayRequest = new BufferGroupRequest(
                requestData.When,
                requestData.PositionTicks,
                requestData.IsPlaying,
                requestData.PlaylistItemId);
            _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
            return NoContent();
        }
        /// 
        /// Notify SyncPlay group that member is ready for playback.
        /// 
        /// The player status.
        /// Group state update sent to all group members.
        /// A  indicating success.
        [HttpPost("Ready")]
        [ProducesResponseType(StatusCodes.Status204NoContent)]
        [Authorize(Policy = Policies.SyncPlayIsInGroup)]
        public ActionResult SyncPlayReady(
            [FromBody, Required] ReadyRequestDto requestData)
        {
            var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request);
            var syncPlayRequest = new ReadyGroupRequest(
                requestData.When,
                requestData.PositionTicks,
                requestData.IsPlaying,
                requestData.PlaylistItemId);
            _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
            return NoContent();
        }
        /// 
        /// Request SyncPlay group to ignore member during group-wait.
        /// 
        /// The settings to set.
        /// Member state updated.
        /// A  indicating success.
        [HttpPost("SetIgnoreWait")]
        [ProducesResponseType(StatusCodes.Status204NoContent)]
        [Authorize(Policy = Policies.SyncPlayIsInGroup)]
        public ActionResult SyncPlaySetIgnoreWait(
            [FromBody, Required] IgnoreWaitRequestDto requestData)
        {
            var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request);
            var syncPlayRequest = new IgnoreWaitGroupRequest(requestData.IgnoreWait);
            _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
            return NoContent();
        }
        /// 
        /// Request next item in SyncPlay group.
        /// 
        /// The current item information.
        /// Next item update sent to all group members.
        /// A  indicating success.
        [HttpPost("NextItem")]
        [ProducesResponseType(StatusCodes.Status204NoContent)]
        [Authorize(Policy = Policies.SyncPlayIsInGroup)]
        public ActionResult SyncPlayNextItem(
            [FromBody, Required] NextItemRequestDto requestData)
        {
            var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request);
            var syncPlayRequest = new NextItemGroupRequest(requestData.PlaylistItemId);
            _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
            return NoContent();
        }
        /// 
        /// Request previous item in SyncPlay group.
        /// 
        /// The current item information.
        /// Previous item update sent to all group members.
        /// A  indicating success.
        [HttpPost("PreviousItem")]
        [ProducesResponseType(StatusCodes.Status204NoContent)]
        [Authorize(Policy = Policies.SyncPlayIsInGroup)]
        public ActionResult SyncPlayPreviousItem(
            [FromBody, Required] PreviousItemRequestDto requestData)
        {
            var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request);
            var syncPlayRequest = new PreviousItemGroupRequest(requestData.PlaylistItemId);
            _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
            return NoContent();
        }
        /// 
        /// Request to set repeat mode in SyncPlay group.
        /// 
        /// The new repeat mode.
        /// Play queue update sent to all group members.
        /// A  indicating success.
        [HttpPost("SetRepeatMode")]
        [ProducesResponseType(StatusCodes.Status204NoContent)]
        [Authorize(Policy = Policies.SyncPlayIsInGroup)]
        public ActionResult SyncPlaySetRepeatMode(
            [FromBody, Required] SetRepeatModeRequestDto requestData)
        {
            var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request);
            var syncPlayRequest = new SetRepeatModeGroupRequest(requestData.Mode);
            _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
            return NoContent();
        }
        /// 
        /// Request to set shuffle mode in SyncPlay group.
        /// 
        /// The new shuffle mode.
        /// Play queue update sent to all group members.
        /// A  indicating success.
        [HttpPost("SetShuffleMode")]
        [ProducesResponseType(StatusCodes.Status204NoContent)]
        [Authorize(Policy = Policies.SyncPlayIsInGroup)]
        public ActionResult SyncPlaySetShuffleMode(
            [FromBody, Required] SetShuffleModeRequestDto requestData)
        {
            var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request);
            var syncPlayRequest = new SetShuffleModeGroupRequest(requestData.Mode);
            _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
            return NoContent();
        }
        /// 
        /// Update session ping.
        /// 
        /// The new ping.
        /// Ping updated.
        /// A  indicating success.
        [HttpPost("Ping")]
        [ProducesResponseType(StatusCodes.Status204NoContent)]
        public ActionResult SyncPlayPing(
            [FromBody, Required] PingRequestDto requestData)
        {
            var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request);
            var syncPlayRequest = new PingGroupRequest(requestData.Ping);
            _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
            return NoContent();
        }
    }
}