using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace Optimizer
{
    internal static class StartupHelper
    {
        internal static readonly string LocalMachineRun = "Software\\Microsoft\\Windows\\CurrentVersion\\Run";
        internal static readonly string LocalMachineRunOnce = "Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce";
        internal static readonly string LocalMachineRunWoW = "Software\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Run";
        internal static readonly string LocalMachineRunOnceWow = "Software\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\RunOnce";
        internal static readonly string CurrentUserRun = "Software\\Microsoft\\Windows\\CurrentVersion\\Run";
        internal static readonly string CurrentUserRunOnce = "Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce";

        internal static readonly string LocalMachineStartupFolder = CleanHelper.ProgramData + "\\Microsoft\\Windows\\Start Menu\\Programs\\Startup";
        internal static readonly string CurrentUserStartupFolder = CleanHelper.ProfileAppDataRoaming + "\\Microsoft\\Windows\\Start Menu\\Programs\\Startup";

        private static void GetRegistryStartupItemsHelper(ref List<StartupItem> list, StartupItemLocation location, StartupItemType type)
        {
            string keyPath = string.Empty;
            RegistryKey hive = null;

            if (location == StartupItemLocation.HKLM)
            {
                hive = Registry.LocalMachine;

                if (type == StartupItemType.Run)
                {
                    keyPath = LocalMachineRun;
                }
                else if (type == StartupItemType.RunOnce)
                {
                    keyPath = LocalMachineRunOnce;
                }
            }
            else if (location == StartupItemLocation.HKLMWoW)
            {
                hive = Registry.LocalMachine;

                if (type == StartupItemType.Run)
                {
                    keyPath = LocalMachineRunWoW;
                }
                else if (type == StartupItemType.RunOnce)
                {
                    keyPath = LocalMachineRunOnceWow;
                }
            }
            else if (location == StartupItemLocation.HKCU)
            {
                hive = Registry.CurrentUser;

                if (type == StartupItemType.Run)
                {
                    keyPath = CurrentUserRun;
                }
                else if (type == StartupItemType.RunOnce)
                {
                    keyPath = CurrentUserRunOnce;
                }
            }

            if (hive != null)
            {
                try
                {
                    RegistryKey key = hive.OpenSubKey(keyPath, true);

                    if (key != null)
                    {
                        string[] valueNames = key.GetValueNames();

                        foreach (string x in valueNames)
                        {
                            try
                            {
                                RegistryStartupItem item = new RegistryStartupItem();
                                item.Name = x;
                                item.FileLocation = key.GetValue(x).ToString();
                                item.Key = key;
                                item.RegistryLocation = location;
                                item.StartupType = type;

                                list.Add(item);
                            }
                            catch (Exception ex)
                            {
                                Logger.LogError("Utilities.GetRegistryStartupItemsHelper", ex.Message, ex.StackTrace);
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    Logger.LogError("Utilities.GetRegistryStartupItemsHelper", ex.Message, ex.StackTrace);
                }
            }
        }

        private static void GetFolderStartupItemsHelper(ref List<StartupItem> list, IEnumerable<string> files, IEnumerable<string> shortcuts, StartupItemLocation folderOrigin)
        {
            foreach (string file in files)
            {
                try
                {
                    FolderStartupItem item = new FolderStartupItem();
                    item.Name = Path.GetFileNameWithoutExtension(file);
                    item.FileLocation = file;
                    item.Shortcut = file;
                    item.RegistryLocation = folderOrigin;

                    list.Add(item);
                }
                catch (Exception ex)
                {
                    Logger.LogError("Utilities.GetFolderStartupItemsHelper", ex.Message, ex.StackTrace);
                }
            }

            foreach (string shortcut in shortcuts)
            {
                try
                {
                    FolderStartupItem item = new FolderStartupItem();
                    item.Name = Path.GetFileNameWithoutExtension(shortcut);
                    item.FileLocation = Utilities.GetShortcutTargetFile(shortcut);
                    item.Shortcut = shortcut;
                    item.RegistryLocation = folderOrigin;

                    list.Add(item);
                }
                catch (Exception ex)
                {
                    Logger.LogError("Utilities.GetFolderStartupItemsHelper", ex.Message, ex.StackTrace);
                }
            }
        }

        internal static List<StartupItem> GetStartupItems()
        {
            List<StartupItem> startupItems = new List<StartupItem>();

            GetRegistryStartupItemsHelper(ref startupItems, StartupItemLocation.HKLM, StartupItemType.Run);
            GetRegistryStartupItemsHelper(ref startupItems, StartupItemLocation.HKLM, StartupItemType.RunOnce);

            GetRegistryStartupItemsHelper(ref startupItems, StartupItemLocation.HKCU, StartupItemType.Run);
            GetRegistryStartupItemsHelper(ref startupItems, StartupItemLocation.HKCU, StartupItemType.RunOnce);

            if (Environment.Is64BitOperatingSystem)
            {
                GetRegistryStartupItemsHelper(ref startupItems, StartupItemLocation.HKLMWoW, StartupItemType.Run);
                GetRegistryStartupItemsHelper(ref startupItems, StartupItemLocation.HKLMWoW, StartupItemType.RunOnce);
            }

            if (Directory.Exists(CurrentUserStartupFolder))
            {
                IEnumerable<string> currentUserFiles = Directory.EnumerateFiles(CurrentUserStartupFolder, "*.*", SearchOption.AllDirectories)
                    .Where(s => s.EndsWith(".exe") || s.EndsWith(".bat") || s.EndsWith(".cmd"));

                IEnumerable<string> currentUserShortcuts = Directory.GetFiles(CurrentUserStartupFolder, "*.lnk", SearchOption.AllDirectories);

                GetFolderStartupItemsHelper(ref startupItems, currentUserFiles, currentUserShortcuts, StartupItemLocation.CUStartupFolder);
            }

            if (Directory.Exists(LocalMachineStartupFolder))
            {
                IEnumerable<string> localMachineFiles = Directory.EnumerateFiles(LocalMachineStartupFolder, "*.*", SearchOption.AllDirectories)
                    .Where(s => s.EndsWith(".exe") || s.EndsWith(".bat") || s.EndsWith(".cmd"));

                IEnumerable<string> localMachineShortcuts = Directory.GetFiles(LocalMachineStartupFolder, "*.lnk", SearchOption.AllDirectories);

                GetFolderStartupItemsHelper(ref startupItems, localMachineFiles, localMachineShortcuts, StartupItemLocation.LMStartupFolder);
            }

            return startupItems;
        }
    }
}
