using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Serialization;
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Controller.Entities
{
    /// 
    /// Class User
    /// 
    public class User : BaseItem
    {
        public static IUserManager UserManager { get; set; }
        public static IXmlSerializer XmlSerializer { get; set; }
        /// 
        /// Gets or sets the password.
        /// 
        /// The password.
        public string Password { get; set; }
        /// 
        /// Gets or sets the path.
        /// 
        /// The path.
        [IgnoreDataMember]
        public override string Path
        {
            get
            {
                // Return this so that metadata providers will look in here
                return ConfigurationDirectoryPath;
            }
            set
            {
                base.Path = value;
            }
        }
        /// 
        /// Returns the folder containing the item.
        /// If the item is a folder, it returns the folder itself
        /// 
        /// The containing folder path.
        public override string ContainingFolderPath
        {
            get
            {
                return Path;
            }
        }
        /// 
        /// Gets a value indicating whether this instance is owned item.
        /// 
        /// true if this instance is owned item; otherwise, false.
        public override bool IsOwnedItem
        {
            get
            {
                return false;
            }
        }
        /// 
        /// Gets the root folder.
        /// 
        /// The root folder.
        [IgnoreDataMember]
        public Folder RootFolder
        {
            get
            {
                return LibraryManager.GetUserRootFolder();
            }
        }
        /// 
        /// Gets or sets the last login date.
        /// 
        /// The last login date.
        public DateTime? LastLoginDate { get; set; }
        /// 
        /// Gets or sets the last activity date.
        /// 
        /// The last activity date.
        public DateTime? LastActivityDate { get; set; }
        /// 
        /// The _configuration
        /// 
        private UserConfiguration _configuration;
        /// 
        /// The _configuration initialized
        /// 
        private bool _configurationInitialized;
        /// 
        /// The _configuration sync lock
        /// 
        private object _configurationSyncLock = new object();
        /// 
        /// Gets the user's configuration
        /// 
        /// The configuration.
        [IgnoreDataMember]
        public UserConfiguration Configuration
        {
            get
            {
                // Lazy load
                LazyInitializer.EnsureInitialized(ref _configuration, ref _configurationInitialized, ref _configurationSyncLock, () => (UserConfiguration)ConfigurationHelper.GetXmlConfiguration(typeof(UserConfiguration), ConfigurationFilePath, XmlSerializer));
                return _configuration;
            }
            private set
            {
                _configuration = value;
                _configurationInitialized = value != null;
            }
        }
        /// 
        /// Renames the user.
        /// 
        /// The new name.
        /// Task.
        /// 
        public Task Rename(string newName)
        {
            if (string.IsNullOrEmpty(newName))
            {
                throw new ArgumentNullException();
            }
            // If only the casing is changing, leave the file system alone
            if (!newName.Equals(Name, StringComparison.OrdinalIgnoreCase))
            {
                // Move configuration
                var newConfigDirectory = GetConfigurationDirectoryPath(newName);
                var oldConfigurationDirectory = ConfigurationDirectoryPath;
                // Exceptions will be thrown if these paths already exist
                if (Directory.Exists(newConfigDirectory))
                {
                    Directory.Delete(newConfigDirectory, true);
                }
                if (Directory.Exists(oldConfigurationDirectory))
                {
                    Directory.Move(oldConfigurationDirectory, newConfigDirectory);
                }
                else
                {
                    Directory.CreateDirectory(newConfigDirectory);
                }
            }
            Name = newName;
            return RefreshMetadata(new MetadataRefreshOptions
            {
                ReplaceAllMetadata = true,
                ImageRefreshMode = ImageRefreshMode.FullRefresh,
                MetadataRefreshMode = MetadataRefreshMode.FullRefresh
            }, CancellationToken.None);
        }
        public override Task UpdateToRepository(ItemUpdateType updateReason, CancellationToken cancellationToken)
        {
            return UserManager.UpdateUser(this);
        }
        /// 
        /// Gets the path to the user's configuration directory
        /// 
        /// The configuration directory path.
        [IgnoreDataMember]
        public string ConfigurationDirectoryPath
        {
            get
            {
                return GetConfigurationDirectoryPath(Name);
            }
        }
        /// 
        /// Gets the configuration directory path.
        /// 
        /// The username.
        /// System.String.
        private string GetConfigurationDirectoryPath(string username)
        {
            if (string.IsNullOrEmpty(username))
            {
                throw new ArgumentNullException("username");
            }
            var safeFolderName = FileSystem.GetValidFilename(username);
            return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.UserConfigurationDirectoryPath, safeFolderName);
        }
        /// 
        /// Gets the path to the user's configuration file
        /// 
        /// The configuration file path.
        [IgnoreDataMember]
        public string ConfigurationFilePath
        {
            get
            {
                return System.IO.Path.Combine(ConfigurationDirectoryPath, "config.xml");
            }
        }
        /// 
        /// Saves the current configuration to the file system
        /// 
        public void SaveConfiguration()
        {
            var xmlPath = ConfigurationFilePath;
            Directory.CreateDirectory(System.IO.Path.GetDirectoryName(xmlPath));
            XmlSerializer.SerializeToFile(Configuration, xmlPath);
        }
        /// 
        /// Updates the configuration.
        /// 
        /// The config.
        /// The serializer.
        /// config
        public void UpdateConfiguration(UserConfiguration config, IXmlSerializer serializer)
        {
            if (config == null)
            {
                throw new ArgumentNullException("config");
            }
            Configuration = config;
            SaveConfiguration();
        }
    }
}