using System;
using System.Globalization;
using System.Linq;
using System.Threading;
using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.Helpers;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace Jellyfin.Api.Controllers
{
    /// 
    /// The videos controller.
    /// 
    [Route("Videos")]
    public class VideosController : BaseJellyfinApiController
    {
        private readonly ILibraryManager _libraryManager;
        private readonly IUserManager _userManager;
        private readonly IDtoService _dtoService;
        /// 
        /// Initializes a new instance of the  class.
        /// 
        /// Instance of the  interface.
        /// Instance of the  interface.
        /// Instance of the  interface.
        public VideosController(
            ILibraryManager libraryManager,
            IUserManager userManager,
            IDtoService dtoService)
        {
            _libraryManager = libraryManager;
            _userManager = userManager;
            _dtoService = dtoService;
        }
        /// 
        /// Gets additional parts for a video.
        /// 
        /// The item id.
        /// Optional. Filter by user id, and attach user data.
        /// Additional parts returned.
        /// A  with the parts.
        [HttpGet("{itemId}/AdditionalParts")]
        [Authorize]
        [ProducesResponseType(StatusCodes.Status200OK)]
        public ActionResult> GetAdditionalPart([FromRoute] Guid itemId, [FromQuery] Guid userId)
        {
            var user = !userId.Equals(Guid.Empty) ? _userManager.GetUserById(userId) : null;
            var item = itemId.Equals(Guid.Empty)
                ? (!userId.Equals(Guid.Empty)
                    ? _libraryManager.GetUserRootFolder()
                    : _libraryManager.RootFolder)
                : _libraryManager.GetItemById(itemId);
            var dtoOptions = new DtoOptions();
            dtoOptions = dtoOptions.AddClientFields(Request);
            BaseItemDto[] items;
            if (item is Video video)
            {
                items = video.GetAdditionalParts()
                    .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, video))
                    .ToArray();
            }
            else
            {
                items = Array.Empty();
            }
            var result = new QueryResult
            {
                Items = items,
                TotalRecordCount = items.Length
            };
            return result;
        }
        /// 
        /// Removes alternate video sources.
        /// 
        /// The item id.
        /// Alternate sources deleted.
        /// Video not found.
        /// A  indicating success, or a  if the video doesn't exist.
        [HttpDelete("{itemId}/AlternateSources")]
        [Authorize(Policy = Policies.RequiresElevation)]
        [ProducesResponseType(StatusCodes.Status200OK)]
        [ProducesResponseType(StatusCodes.Status404NotFound)]
        public ActionResult DeleteAlternateSources([FromRoute] Guid itemId)
        {
            var video = (Video)_libraryManager.GetItemById(itemId);
            if (video == null)
            {
                return NotFound("The video either does not exist or the id does not belong to a video.");
            }
            foreach (var link in video.GetLinkedAlternateVersions())
            {
                link.SetPrimaryVersionId(null);
                link.LinkedAlternateVersions = Array.Empty();
                link.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None);
            }
            video.LinkedAlternateVersions = Array.Empty();
            video.SetPrimaryVersionId(null);
            video.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None);
            return NoContent();
        }
        /// 
        /// Merges videos into a single record.
        /// 
        /// Item id list. This allows multiple, comma delimited.
        /// Videos merged.
        /// Supply at least 2 video ids.
        /// A  indicating success, or a  if less than two ids were supplied.
        [HttpPost("MergeVersions")]
        [Authorize(Policy = Policies.RequiresElevation)]
        [ProducesResponseType(StatusCodes.Status204NoContent)]
        [ProducesResponseType(StatusCodes.Status400BadRequest)]
        public ActionResult MergeVersions([FromQuery] string itemIds)
        {
            var items = RequestHelpers.Split(itemIds, ',', true)
                .Select(i => _libraryManager.GetItemById(i))
                .OfType