using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.Helpers;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Querying;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace Jellyfin.Api.Controllers
{
    /// 
    /// The albums controller.
    /// 
    [Route("")]
    public class AlbumsController : BaseJellyfinApiController
    {
        private readonly IUserManager _userManager;
        private readonly ILibraryManager _libraryManager;
        private readonly IDtoService _dtoService;
        /// 
        /// Initializes a new instance of the  class.
        /// 
        /// Instance of the  interface.
        /// Instance of the  interface.
        /// Instance of the  interface.
        public AlbumsController(
            IUserManager userManager,
            ILibraryManager libraryManager,
            IDtoService dtoService)
        {
            _userManager = userManager;
            _libraryManager = libraryManager;
            _dtoService = dtoService;
        }
        /// 
        /// Finds albums similar to a given album.
        /// 
        /// The album id.
        /// Optional. Filter by user id, and attach user data.
        /// Optional. Ids of artists to exclude.
        /// Optional. The maximum number of records to return.
        /// Similar albums returned.
        /// A  with similar albums.
        [HttpGet("Albums/{albumId}/Similar")]
        [ProducesResponseType(StatusCodes.Status200OK)]
        public ActionResult> GetSimilarAlbums(
            [FromRoute, Required] string albumId,
            [FromQuery] Guid? userId,
            [FromQuery] string? excludeArtistIds,
            [FromQuery] int? limit)
        {
            var dtoOptions = new DtoOptions().AddClientFields(Request);
            return SimilarItemsHelper.GetSimilarItemsResult(
                dtoOptions,
                _userManager,
                _libraryManager,
                _dtoService,
                userId,
                albumId,
                excludeArtistIds,
                limit,
                new[] { typeof(MusicAlbum) },
                GetAlbumSimilarityScore);
        }
        /// 
        /// Finds artists similar to a given artist.
        /// 
        /// The artist id.
        /// Optional. Filter by user id, and attach user data.
        /// Optional. Ids of artists to exclude.
        /// Optional. The maximum number of records to return.
        /// Similar artists returned.
        /// A  with similar artists.
        [HttpGet("Artists/{artistId}/Similar")]
        [ProducesResponseType(StatusCodes.Status200OK)]
        public ActionResult> GetSimilarArtists(
            [FromRoute, Required] string artistId,
            [FromQuery] Guid? userId,
            [FromQuery] string? excludeArtistIds,
            [FromQuery] int? limit)
        {
            var dtoOptions = new DtoOptions().AddClientFields(Request);
            return SimilarItemsHelper.GetSimilarItemsResult(
                dtoOptions,
                _userManager,
                _libraryManager,
                _dtoService,
                userId,
                artistId,
                excludeArtistIds,
                limit,
                new[] { typeof(MusicArtist) },
                SimilarItemsHelper.GetSimiliarityScore);
        }
        /// 
        /// Gets a similairty score of two albums.
        /// 
        /// The first item.
        /// The item1 people.
        /// All people.
        /// The second item.
        /// System.Int32.
        private int GetAlbumSimilarityScore(BaseItem item1, List item1People, List allPeople, BaseItem item2)
        {
            var points = SimilarItemsHelper.GetSimiliarityScore(item1, item1People, allPeople, item2);
            var album1 = (MusicAlbum)item1;
            var album2 = (MusicAlbum)item2;
            var artists1 = album1
                .GetAllArtists()
                .DistinctNames()
                .ToList();
            var artists2 = new HashSet(
                album2.GetAllArtists().DistinctNames(),
                StringComparer.OrdinalIgnoreCase);
            return points + artists1.Where(artists2.Contains).Sum(i => 5);
        }
    }
}