using System.Deployment.Application;
using Microsoft.Win32;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Security.AccessControl;
namespace MediaBrowser.ClickOnce
{
    /// 
    /// Class ClickOnceHelper
    /// 
    public class ClickOnceHelper
    {
        /// 
        /// The uninstall string
        /// 
        private const string UninstallString = "UninstallString";
        /// 
        /// The display name key
        /// 
        private const string DisplayNameKey = "DisplayName";
        /// 
        /// The uninstall string file
        /// 
        private const string UninstallStringFile = "UninstallString.bat";
        /// 
        /// The appref extension
        /// 
        private const string ApprefExtension = ".appref-ms";
        /// 
        /// The uninstall registry key
        /// 
        private readonly RegistryKey UninstallRegistryKey;
        /// 
        /// Gets the location.
        /// 
        /// The location.
        private static string Location
        {
            get { return Assembly.GetExecutingAssembly().Location; }
        }
        /// 
        /// Gets a value indicating whether this instance is network deployed.
        /// 
        /// true if this instance is network deployed; otherwise, false.
        public static bool IsNetworkDeployed
        {
            get { return ApplicationDeployment.IsNetworkDeployed; }
        }
        /// 
        /// Gets the name of the publisher.
        /// 
        /// The name of the publisher.
        public string PublisherName { get; private set; }
        /// 
        /// Gets the name of the product.
        /// 
        /// The name of the product.
        public string ProductName { get; private set; }
        /// 
        /// Gets the uninstall file.
        /// 
        /// The uninstall file.
        public string UninstallFile { get; private set; }
        /// 
        /// Gets the name of the suite.
        /// 
        /// The name of the suite.
        public string SuiteName { get; private set; }
        /// 
        /// Initializes a new instance of the  class.
        /// 
        /// Name of the publisher.
        /// Name of the product.
        /// Name of the suite.
        public ClickOnceHelper(string publisherName, string productName, string suiteName)
        {
            PublisherName = publisherName;
            ProductName = productName;
            SuiteName = suiteName;
            var publisherFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), PublisherName);
            if (!Directory.Exists(publisherFolder))
            {
                Directory.CreateDirectory(publisherFolder);
            }
            UninstallFile = Path.Combine(publisherFolder, UninstallStringFile);
            UninstallRegistryKey = GetUninstallRegistryKeyByProductName(ProductName);
        }
        /// 
        /// Gets the shortcut path.
        /// 
        /// System.String.
        private string GetShortcutPath()
        {
            var allProgramsPath = Environment.GetFolderPath(Environment.SpecialFolder.Programs);
            var shortcutPath = Path.Combine(allProgramsPath, PublisherName);
            if (!string.IsNullOrEmpty(SuiteName))
            {
                shortcutPath = Path.Combine(shortcutPath, SuiteName);
            }
            return Path.Combine(shortcutPath, ProductName) + ApprefExtension;
        }
        /// 
        /// Gets the startup shortcut path.
        /// 
        /// System.String.
        private string GetStartupShortcutPath()
        {
            var startupPath = Environment.GetFolderPath(Environment.SpecialFolder.Startup);
            
            return Path.Combine(startupPath, ProductName) + ApprefExtension;
        }
        /// 
        /// Adds the shortcut to startup.
        /// 
        public void AddShortcutToStartup()
        {
            var startupPath = GetStartupShortcutPath();
            if (!File.Exists(startupPath))
            {
                File.Copy(GetShortcutPath(), startupPath);
            }
        }
        /// 
        /// Removes the shortcut from startup.
        /// 
        public void RemoveShortcutFromStartup()
        {
            var startupPath = GetStartupShortcutPath();
            if (File.Exists(startupPath))
            {
                File.Delete(startupPath);
            }
        }
        /// 
        /// Updates the uninstall parameters.
        /// 
        /// Name of the uninstaller file.
        public void UpdateUninstallParameters(string uninstallerFileName)
        {
            if (UninstallRegistryKey != null)
            {
                UpdateUninstallString(uninstallerFileName);
            }
        }
        /// 
        /// Gets the name of the uninstall registry key by product.
        /// 
        /// Name of the product.
        /// RegistryKey.
        private RegistryKey GetUninstallRegistryKeyByProductName(string productName)
        {
            var subKey = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Uninstall");
            if (subKey == null)
            {
                return null;
            }
            return subKey.GetSubKeyNames()
                .Select(name => subKey.OpenSubKey(name, RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.QueryValues | RegistryRights.ReadKey | RegistryRights.SetValue))
                .Where(application => application != null)
                .FirstOrDefault(application => application.GetValueNames().Where(appKey => appKey.Equals(DisplayNameKey)).Any(appKey => application.GetValue(appKey).Equals(productName)));
        }
        /// 
        /// Updates the uninstall string.
        /// 
        /// Name of the uninstaller file.
        private void UpdateUninstallString(string uninstallerFileName)
        {
            var uninstallString = (string)UninstallRegistryKey.GetValue(UninstallString);
            if (!string.IsNullOrEmpty(UninstallFile) && uninstallString.StartsWith("rundll32.exe", StringComparison.OrdinalIgnoreCase))
            {
                File.WriteAllText(UninstallFile, uninstallString);
            }
            var str = String.Format("\"{0}\" uninstall", Path.Combine(Path.GetDirectoryName(Location), uninstallerFileName));
            UninstallRegistryKey.SetValue(UninstallString, str);
        }
        /// 
        /// Uninstalls this instance.
        /// 
        public void Uninstall()
        {
            RemoveShortcutFromStartup();
            var uninstallString = File.ReadAllText(UninstallFile);
            new Process
            {
                StartInfo =
                {
                    Arguments = uninstallString.Substring(uninstallString.IndexOf(" ", StringComparison.OrdinalIgnoreCase) + 1),
                    FileName = uninstallString.Substring(0, uninstallString.IndexOf(" ", StringComparison.OrdinalIgnoreCase)),
                    UseShellExecute = false
                }
            }.Start();
        }
        /// 
        /// Configures the click once startup.
        /// 
        /// Name of the publisher.
        /// Name of the product.
        /// Name of the suite.
        /// if set to true [run at startup].
        /// The uninstaller filename.
        public static void ConfigureClickOnceStartupIfInstalled(string publisherName, string productName, string suiteName, bool runAtStartup, string uninstallerFilename)
        {
            if (!ApplicationDeployment.IsNetworkDeployed)
            {
                return;
            }
            var clickOnceHelper = new ClickOnceHelper(publisherName, productName, suiteName);
            if (runAtStartup)
            {
                clickOnceHelper.UpdateUninstallParameters(uninstallerFilename);
                clickOnceHelper.AddShortcutToStartup();
            }
            else
            {
                clickOnceHelper.RemoveShortcutFromStartup();
            }
        }
    }
}