using MediaBrowser.ApiInteraction;
using MediaBrowser.Common.IO;
using MediaBrowser.Common.Kernel;
using MediaBrowser.Common.Logging;
using MediaBrowser.Model.Connectivity;
using MediaBrowser.Model.Net;
using MediaBrowser.UI.Configuration;
using MediaBrowser.UI.Playback;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Cache;
using System.Net.Http;
using System.Reflection;
using System.Threading.Tasks;
namespace MediaBrowser.UI.Controller
{
    /// 
    /// This controls application logic as well as server interaction within the UI.
    /// 
    public class UIKernel : BaseKernel
    {
        /// 
        /// Gets the instance.
        /// 
        /// The instance.
        public static UIKernel Instance { get; private set; }
        /// 
        /// Gets the API client.
        /// 
        /// The API client.
        public ApiClient ApiClient { get; private set; }
        /// 
        /// Gets the playback manager.
        /// 
        /// The playback manager.
        public PlaybackManager PlaybackManager { get; private set; }
        /// 
        /// Initializes a new instance of the  class.
        /// 
        public UIKernel(IIsoManager isoManager)
            : base(isoManager)
        {
            Instance = this;
        }
        /// 
        /// Gets the media players.
        /// 
        /// The media players.
        [ImportMany(typeof(BaseMediaPlayer))]
        public IEnumerable MediaPlayers { get; private set; }
        /// 
        /// Gets the list of currently loaded themes
        /// 
        /// The themes.
        [ImportMany(typeof(BaseTheme))]
        public IEnumerable Themes { get; private set; }
        /// 
        /// Gets the kernel context.
        /// 
        /// The kernel context.
        public override KernelContext KernelContext
        {
            get { return KernelContext.Ui; }
        }
        /// 
        /// Gets the UDP server port number.
        /// 
        /// The UDP server port number.
        public override int UdpServerPortNumber
        {
            get { return 7360; }
        }
        /// 
        /// Give the UI a different url prefix so that they can share the same port, in case they are installed on the same machine.
        /// 
        /// The HTTP server URL prefix.
        public override string HttpServerUrlPrefix
        {
            get
            {
                return "http://+:" + Configuration.HttpServerPortNumber + "/mediabrowserui/";
            }
        }
        /// 
        /// Reload api client and update plugins after loading configuration
        /// 
        /// Task.
        protected override async Task OnConfigurationLoaded()
        {
            ReloadApiClient();
            try
            {
                await new PluginUpdater(Logger).UpdatePlugins().ConfigureAwait(false);
            }
            catch (HttpException ex)
            {
                Logger.ErrorException("Error updating plugins from the server", ex);
            }
        }
        /// 
        /// Disposes the current ApiClient and creates a new one
        /// 
        private void ReloadApiClient()
        {
            DisposeApiClient();
            var logger = LogManager.GetLogger("ApiClient");
            ApiClient = new ApiClient(logger, new AsyncHttpClient(new WebRequestHandler
            {
                AutomaticDecompression = DecompressionMethods.Deflate,
                CachePolicy = new RequestCachePolicy(RequestCacheLevel.Revalidate)
            }))
            {
                ServerHostName = Configuration.ServerHostName,
                ServerApiPort = Configuration.ServerApiPort,
                ClientType = ClientType.Pc,
                DeviceName = Environment.MachineName,
                SerializationFormat = SerializationFormats.Json
            };
        }
        /// 
        /// Reloads the internal.
        /// 
        /// Task.
        protected override Task ReloadInternal()
        {
            PlaybackManager = new PlaybackManager(this);
            return base.ReloadInternal();
        }
        /// 
        /// Called when [composable parts loaded].
        /// 
        /// Task.
        protected override async Task OnComposablePartsLoaded()
        {
            await base.OnComposablePartsLoaded().ConfigureAwait(false);
            // Once plugins have loaded give the api a reference to our protobuf serializer
            DataSerializer.DynamicSerializer = ProtobufSerializer.TypeModel;
        }
        /// 
        /// Disposes the current ApiClient
        /// 
        private void DisposeApiClient()
        {
            if (ApiClient != null)
            {
                ApiClient.Dispose();
            }
        }
        /// 
        /// Releases unmanaged and - optionally - managed resources.
        /// 
        /// true to release both managed and unmanaged resources; false to release only unmanaged resources.
        protected override void Dispose(bool dispose)
        {
            if (dispose)
            {
                DisposeApiClient();
            }
            base.Dispose(dispose);
        }
    }
}