using System;
using System.ComponentModel.DataAnnotations;
using System.Threading.Tasks;
using Jellyfin.Api.Constants;
using Jellyfin.Data.Dtos;
using Jellyfin.Data.Entities.Security;
using Jellyfin.Data.Queries;
using MediaBrowser.Controller.Devices;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Devices;
using MediaBrowser.Model.Querying;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace Jellyfin.Api.Controllers
{
    /// 
    /// Devices Controller.
    /// 
    [Authorize(Policy = Policies.RequiresElevation)]
    public class DevicesController : BaseJellyfinApiController
    {
        private readonly IDeviceManager _deviceManager;
        private readonly ISessionManager _sessionManager;
        /// 
        /// Initializes a new instance of the  class.
        /// 
        /// Instance of  interface.
        /// Instance of  interface.
        public DevicesController(
            IDeviceManager deviceManager,
            ISessionManager sessionManager)
        {
            _deviceManager = deviceManager;
            _sessionManager = sessionManager;
        }
        /// 
        /// Get Devices.
        /// 
        /// Gets or sets a value indicating whether [supports synchronize].
        /// Gets or sets the user identifier.
        /// Devices retrieved.
        /// An  containing the list of devices.
        [HttpGet]
        [ProducesResponseType(StatusCodes.Status200OK)]
        public async Task>> GetDevices([FromQuery] bool? supportsSync, [FromQuery] Guid? userId)
        {
            return await _deviceManager.GetDevicesForUser(userId, supportsSync).ConfigureAwait(false);
        }
        /// 
        /// Get info for a device.
        /// 
        /// Device Id.
        /// Device info retrieved.
        /// Device not found.
        /// An  containing the device info on success, or a  if the device could not be found.
        [HttpGet("Info")]
        [ProducesResponseType(StatusCodes.Status200OK)]
        [ProducesResponseType(StatusCodes.Status404NotFound)]
        public async Task> GetDeviceInfo([FromQuery, Required] string id)
        {
            var deviceInfo = await _deviceManager.GetDevice(id).ConfigureAwait(false);
            if (deviceInfo == null)
            {
                return NotFound();
            }
            return deviceInfo;
        }
        /// 
        /// Get options for a device.
        /// 
        /// Device Id.
        /// Device options retrieved.
        /// Device not found.
        /// An  containing the device info on success, or a  if the device could not be found.
        [HttpGet("Options")]
        [ProducesResponseType(StatusCodes.Status200OK)]
        [ProducesResponseType(StatusCodes.Status404NotFound)]
        public async Task> GetDeviceOptions([FromQuery, Required] string id)
        {
            var deviceInfo = await _deviceManager.GetDeviceOptions(id).ConfigureAwait(false);
            if (deviceInfo == null)
            {
                return NotFound();
            }
            return deviceInfo;
        }
        /// 
        /// Update device options.
        /// 
        /// Device Id.
        /// Device Options.
        /// Device options updated.
        /// A .
        [HttpPost("Options")]
        [ProducesResponseType(StatusCodes.Status204NoContent)]
        public async Task UpdateDeviceOptions(
            [FromQuery, Required] string id,
            [FromBody, Required] DeviceOptionsDto deviceOptions)
        {
            await _deviceManager.UpdateDeviceOptions(id, deviceOptions.CustomName).ConfigureAwait(false);
            return NoContent();
        }
        /// 
        /// Deletes a device.
        /// 
        /// Device Id.
        /// Device deleted.
        /// Device not found.
        /// A  on success, or a  if the device could not be found.
        [HttpDelete]
        [ProducesResponseType(StatusCodes.Status204NoContent)]
        [ProducesResponseType(StatusCodes.Status404NotFound)]
        public async Task DeleteDevice([FromQuery, Required] string id)
        {
            var existingDevice = await _deviceManager.GetDevice(id).ConfigureAwait(false);
            if (existingDevice == null)
            {
                return NotFound();
            }
            var sessions = await _deviceManager.GetDevices(new DeviceQuery { DeviceId = id }).ConfigureAwait(false);
            foreach (var session in sessions.Items)
            {
                await _sessionManager.Logout(session).ConfigureAwait(false);
            }
            return NoContent();
        }
    }
}