// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO.Abstractions;
using System.Linq;
using System.Threading.Tasks;
using CommunityToolkit.WinUI.Controls;
using global::PowerToys.GPOWrapper;
using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Controls;
using Microsoft.PowerToys.Settings.UI.Helpers;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
using Microsoft.PowerToys.Settings.UI.Library.HotkeyConflicts;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
using Microsoft.PowerToys.Settings.UI.Services;
using Microsoft.PowerToys.Settings.UI.Views;
using Microsoft.UI.Dispatching;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Settings.UI.Library;

namespace Microsoft.PowerToys.Settings.UI.ViewModels
{
    public partial class DashboardViewModel : PageViewModelBase
    {
        private readonly object _sortLock = new object();

        protected override string ModuleName => "Dashboard";

        private DispatcherQueue dispatcher;

        public Func<string, int> SendConfigMSG { get; }

        public ObservableCollection<DashboardListItem> AllModules { get; set; } = new ObservableCollection<DashboardListItem>();

        public ObservableCollection<DashboardListItem> ShortcutModules { get; set; } = new ObservableCollection<DashboardListItem>();

        public ObservableCollection<DashboardListItem> ActionModules { get; set; } = new ObservableCollection<DashboardListItem>();

        public ObservableCollection<QuickAccessItem> QuickAccessItems => _quickAccessViewModel.Items;

        private readonly QuickAccessViewModel _quickAccessViewModel;

        // Master list of module items that is sorted and projected into AllModules.
        private List<DashboardListItem> _moduleItems = new List<DashboardListItem>();

        // Flag to prevent circular updates when a UI toggle triggers settings changes.
        private bool _isUpdatingFromUI;

        // Flag to prevent toggle operations during sorting to avoid race conditions.
        private bool _isSorting;
        private bool _isDisposed;

        private AllHotkeyConflictsData _allHotkeyConflictsData = new AllHotkeyConflictsData();

        public AllHotkeyConflictsData AllHotkeyConflictsData
        {
            get => _allHotkeyConflictsData;
            set
            {
                if (Set(ref _allHotkeyConflictsData, value))
                {
                    OnPropertyChanged();
                }
            }
        }

        public string PowerToysVersion
        {
            get
            {
                return Helper.GetProductVersion();
            }
        }

        private DashboardSortOrder _dashboardSortOrder = DashboardSortOrder.Alphabetical;

        public DashboardSortOrder DashboardSortOrder
        {
            get => generalSettingsConfig.DashboardSortOrder;
            set
            {
                if (_dashboardSortOrder != value)
                {
                    _dashboardSortOrder = value;
                    generalSettingsConfig.DashboardSortOrder = value;
                    OutGoingGeneralSettings outgoing = new OutGoingGeneralSettings(generalSettingsConfig);

                    SendConfigMSG(outgoing.ToString());

                    // Notify UI before sorting so menu updates its checked state
                    OnPropertyChanged(nameof(DashboardSortOrder));

                    SortModuleList();
                }
            }
        }

        private ISettingsRepository<GeneralSettings> _settingsRepository;
        private GeneralSettings generalSettingsConfig;
        private Windows.ApplicationModel.Resources.ResourceLoader resourceLoader = Helpers.ResourceLoaderInstance.ResourceLoader;

        public DashboardViewModel(ISettingsRepository<GeneralSettings> settingsRepository, Func<string, int> ipcMSGCallBackFunc)
        {
            dispatcher = DispatcherQueue.GetForCurrentThread();
            _settingsRepository = settingsRepository;
            generalSettingsConfig = settingsRepository.SettingsConfig;

            _settingsRepository.SettingsChanged += OnSettingsChanged;

            // Initialize dashboard sort order from settings
            _dashboardSortOrder = generalSettingsConfig.DashboardSortOrder;

            // set the callback functions value to handle outgoing IPC message.
            SendConfigMSG = ipcMSGCallBackFunc;

            _quickAccessViewModel = new QuickAccessViewModel(
                _settingsRepository,
                new Microsoft.PowerToys.Settings.UI.Controls.QuickAccessLauncher(App.IsElevated),
                moduleType => Helpers.ModuleGpoHelper.GetModuleGpoConfiguration(moduleType) == global::PowerToys.GPOWrapper.GpoRuleConfigured.Disabled,
                moduleType => Helpers.ModuleGpoHelper.GetModuleGpoConfiguration(moduleType) == global::PowerToys.GPOWrapper.GpoRuleConfigured.Enabled,
                resourceLoader);

            BuildModuleList();
            SortModuleList();
            RefreshShortcutModules();
        }

        private void OnSettingsChanged(GeneralSettings newSettings)
        {
            if (_isDisposed)
            {
                return;
            }

            dispatcher.TryEnqueue(() =>
            {
                if (_isDisposed)
                {
                    return;
                }

                generalSettingsConfig = newSettings;

                // Update local field and notify UI if sort order changed
                if (_dashboardSortOrder != generalSettingsConfig.DashboardSortOrder)
                {
                    _dashboardSortOrder = generalSettingsConfig.DashboardSortOrder;
                    OnPropertyChanged(nameof(DashboardSortOrder));
                }

                ModuleEnabledChangedOnSettingsPage();
            });
        }

        protected override void OnConflictsUpdated(object sender, AllHotkeyConflictsEventArgs e)
        {
            if (_isDisposed)
            {
                return;
            }

            dispatcher.TryEnqueue(() =>
            {
                if (_isDisposed)
                {
                    return;
                }

                var allConflictData = e.Conflicts;
                foreach (var inAppConflict in allConflictData.InAppConflicts)
                {
                    var hotkey = inAppConflict.Hotkey;
                    var hotkeySetting = new HotkeySettings(hotkey.Win, hotkey.Ctrl, hotkey.Alt, hotkey.Shift, hotkey.Key);
                    inAppConflict.ConflictIgnored = HotkeyConflictIgnoreHelper.IsIgnoringConflicts(hotkeySetting);
                }

                foreach (var systemConflict in allConflictData.SystemConflicts)
                {
                    var hotkey = systemConflict.Hotkey;
                    var hotkeySetting = new HotkeySettings(hotkey.Win, hotkey.Ctrl, hotkey.Alt, hotkey.Shift, hotkey.Key);
                    systemConflict.ConflictIgnored = HotkeyConflictIgnoreHelper.IsIgnoringConflicts(hotkeySetting);
                }

                AllHotkeyConflictsData = e.Conflicts ?? new AllHotkeyConflictsData();
            });
        }

        private void RequestConflictData()
        {
            // Request current conflicts data
            GlobalHotkeyConflictManager.Instance?.RequestAllConflicts();
        }

        /// <summary>
        /// Builds the master list of module items. Called once during initialization.
        /// Each module item contains its configuration, enabled state, and GPO lock status.
        /// </summary>
        private void BuildModuleList()
        {
            _moduleItems.Clear();

            foreach (ModuleType moduleType in Enum.GetValues<ModuleType>())
            {
                if (moduleType == ModuleType.GeneralSettings)
                {
                    continue;
                }

                GpoRuleConfigured gpo = ModuleGpoHelper.GetModuleGpoConfiguration(moduleType);
                var newItem = new DashboardListItem()
                {
                    Tag = moduleType,
                    Label = resourceLoader.GetString(ModuleHelper.GetModuleLabelResourceName(moduleType)),
                    IsEnabled = gpo == GpoRuleConfigured.Enabled || (gpo != GpoRuleConfigured.Disabled && ModuleHelper.GetIsModuleEnabled(generalSettingsConfig, moduleType)),
                    IsLocked = gpo == GpoRuleConfigured.Enabled || gpo == GpoRuleConfigured.Disabled,
                    Icon = ModuleHelper.GetModuleTypeFluentIconName(moduleType),
                    IsNew = false,
                    DashboardModuleItems = GetModuleItems(moduleType),
                    ClickCommand = new RelayCommand<object>(DashboardListItemClick),
                };
                newItem.EnabledChangedCallback = EnabledChangedOnUI;
                _moduleItems.Add(newItem);
            }
        }

        /// <summary>
        /// Sorts the module list according to the current sort order and updates the AllModules collection.
        /// On first call, populates AllModules. On subsequent calls, uses Move() to reorder items in-place
        /// to avoid destroying and recreating UI elements.
        /// Temporarily disables interaction on all items during sorting to prevent race conditions.
        /// </summary>
        private void SortModuleList()
        {
            if (_isSorting)
            {
                return;
            }

            lock (_sortLock)
            {
                _isSorting = true;
                try
                {
                    var sortedItems = (DashboardSortOrder switch
                    {
                        DashboardSortOrder.ByStatus => _moduleItems.OrderByDescending(x => x.IsEnabled).ThenBy(x => x.Label),
                        _ => _moduleItems.OrderBy(x => x.Label), // Default alphabetical
                    }).ToList();

                    // If AllModules is empty (first load), just populate it.
                    if (AllModules.Count == 0)
                    {
                        foreach (var item in sortedItems)
                        {
                            AllModules.Add(item);
                        }

                        return;
                    }

                    // Otherwise, update the collection in place using Move to avoid UI glitches.
                    for (int i = 0; i < sortedItems.Count; i++)
                    {
                        var currentItem = sortedItems[i];
                        var currentIndex = AllModules.IndexOf(currentItem);

                        if (currentIndex != -1 && currentIndex != i)
                        {
                            AllModules.Move(currentIndex, i);
                        }
                    }
                }
                finally
                {
                    // Use dispatcher to reset flag after UI updates complete
                    dispatcher.TryEnqueue(DispatcherQueuePriority.Low, () =>
                    {
                        _isSorting = false;
                    });
                }
            }
        }

        /// <summary>
        /// Refreshes module enabled/locked states by re-reading GPO configuration. Only
        /// updates properties that have actually changed to minimize UI notifications
        /// then re-sorts the list according to the current sort order.
        /// </summary>
        private void RefreshModuleList()
        {
            foreach (var item in _moduleItems)
            {
                GpoRuleConfigured gpo = ModuleGpoHelper.GetModuleGpoConfiguration(item.Tag);

                // GPO can force-enable (Enabled) or force-disable (Disabled) a module.
                // If Enabled: module is on and the user cannot disable it.
                // If Disabled: module is off and the user cannot enable it.
                // Otherwise, the setting is unlocked and the user can enable/disable it.
                bool newEnabledState = gpo == GpoRuleConfigured.Enabled || (gpo != GpoRuleConfigured.Disabled && ModuleHelper.GetIsModuleEnabled(generalSettingsConfig, item.Tag));

                // Lock the toggle when GPO is controlling the module.
                bool newLockedState = gpo == GpoRuleConfigured.Enabled || gpo == GpoRuleConfigured.Disabled;

                // Only update if there's an actual change to minimize UI notifications.
                if (item.IsEnabled != newEnabledState)
                {
                    item.UpdateStatus(newEnabledState);
                }

                if (item.IsLocked != newLockedState)
                {
                    item.IsLocked = newLockedState;
                }
            }

            SortModuleList();
        }

        /// <summary>
        /// Callback invoked when a user toggles a module's enabled state in the UI.
        /// Sets the _isUpdatingFromUI flag to prevent circular updates, then updates
        /// settings, re-sorts if needed, and refreshes dependent collections.
        /// </summary>
        private void EnabledChangedOnUI(ModuleListItem item)
        {
            var dashboardListItem = (DashboardListItem)item;
            var isEnabled = dashboardListItem.IsEnabled;

            // Ignore toggle operations during sorting to prevent race conditions.
            // Revert the toggle state since UI already changed due to TwoWay binding.
            if (_isSorting)
            {
                dashboardListItem.UpdateStatus(!isEnabled);
                return;
            }

            _isUpdatingFromUI = true;
            try
            {
                // Send optimized IPC message with only the module status update
                // Format: {"module_status": {"ModuleName": true/false}}
                string moduleKey = ModuleHelper.GetModuleKey(dashboardListItem.Tag);
                string moduleStatusJson = $"{{\"module_status\": {{\"{moduleKey}\": {isEnabled.ToString().ToLowerInvariant()}}}}}";
                SendConfigMSG(moduleStatusJson);

                // Update local settings config to keep UI in sync
                ModuleHelper.SetIsModuleEnabled(generalSettingsConfig, dashboardListItem.Tag, isEnabled);

                if (dashboardListItem.Tag == ModuleType.NewPlus && isEnabled == true)
                {
                    var settingsUtils = SettingsUtils.Default;
                    var settings = NewPlusViewModel.LoadSettings(settingsUtils);
                    NewPlusViewModel.CopyTemplateExamples(settings.Properties.TemplateLocation.Value);
                }

                // Re-sort only required if sorting by enabled status.
                if (DashboardSortOrder == DashboardSortOrder.ByStatus)
                {
                    SortModuleList();
                }

                // Always refresh shortcuts/actions to reflect enabled state changes.
                RefreshShortcutModules();

                // Request updated conflicts after module state change.
                RequestConflictData();
            }
            finally
            {
                _isUpdatingFromUI = false;
            }
        }

        /// <summary>
        /// Callback invoked when module enabled state changes from other parts of the
        /// settings UI. Ignores the notification if it was triggered by a UI toggle
        /// we're already handling, to prevent circular updates.
        /// </summary>
        public void ModuleEnabledChangedOnSettingsPage()
        {
            if (_isDisposed)
            {
                return;
            }

            // Ignore if this was triggered by a UI change that we're already handling.
            if (_isUpdatingFromUI)
            {
                return;
            }

            try
            {
                RefreshModuleList();
                RefreshShortcutModules();

                OnPropertyChanged(nameof(ShortcutModules));

                // Request updated conflicts after module state change.
                RequestConflictData();
            }
            catch (Exception ex)
            {
                Logger.LogError($"Updating active/disabled modules list failed: {ex.Message}");
            }
        }

        /// <summary>
        /// Rebuilds ShortcutModules and ActionModules collections by filtering AllModules
        /// to only include enabled modules and their respective shortcut/action items.
        /// </summary>
        private void RefreshShortcutModules()
        {
            if (_isDisposed)
            {
                return;
            }

            if (!dispatcher.HasThreadAccess)
            {
                _ = dispatcher.TryEnqueue(DispatcherQueuePriority.Normal, RefreshShortcutModules);
                return;
            }

            ShortcutModules.Clear();
            ActionModules.Clear();

            foreach (var x in AllModules.Where(x => x.IsEnabled))
            {
                var filteredItems = x.DashboardModuleItems
                    .Where(m => m is DashboardModuleShortcutItem || m is DashboardModuleActivationItem)
                    .ToList();

                if (filteredItems.Count != 0)
                {
                    var newItem = new DashboardListItem
                    {
                        Icon = x.Icon,
                        IsLocked = x.IsLocked,
                        Label = x.Label,
                        Tag = x.Tag,
                        IsEnabled = x.IsEnabled,
                        DashboardModuleItems = new ObservableCollection<DashboardModuleItem>(filteredItems),
                    };

                    ShortcutModules.Add(newItem);
                    newItem.EnabledChangedCallback = x.EnabledChangedCallback;
                }
            }

            foreach (var x in AllModules.Where(x => x.IsEnabled))
            {
                var filteredItems = x.DashboardModuleItems
                    .Where(m => m is DashboardModuleButtonItem)
                    .ToList();

                if (filteredItems.Count != 0)
                {
                    var newItem = new DashboardListItem
                    {
                        Icon = x.Icon,
                        IsLocked = x.IsLocked,
                        Label = x.Label,
                        Tag = x.Tag,
                        IsEnabled = x.IsEnabled,
                        DashboardModuleItems = new ObservableCollection<DashboardModuleItem>(filteredItems),
                    };

                    ActionModules.Add(newItem);
                    newItem.EnabledChangedCallback = x.EnabledChangedCallback;
                }
            }
        }

        private ObservableCollection<DashboardModuleItem> GetModuleItems(ModuleType moduleType)
        {
            return moduleType switch
            {
                ModuleType.AdvancedPaste => GetModuleItemsAdvancedPaste(),
                ModuleType.AlwaysOnTop => GetModuleItemsAlwaysOnTop(),
                ModuleType.CmdPal => GetModuleItemsCmdPal(),
                ModuleType.ColorPicker => GetModuleItemsColorPicker(),
                ModuleType.CropAndLock => GetModuleItemsCropAndLock(),
                ModuleType.EnvironmentVariables => GetModuleItemsEnvironmentVariables(),
                ModuleType.FancyZones => GetModuleItemsFancyZones(),
                ModuleType.FindMyMouse => GetModuleItemsFindMyMouse(),
                ModuleType.Hosts => GetModuleItemsHosts(),
                ModuleType.KeyboardManager => GetModuleItemsKeyboardManager(),
                ModuleType.LightSwitch => GetModuleItemsLightSwitch(),
                ModuleType.MouseHighlighter => GetModuleItemsMouseHighlighter(),
                ModuleType.MouseJump => GetModuleItemsMouseJump(),
                ModuleType.MousePointerCrosshairs => GetModuleItemsMousePointerCrosshairs(),
                ModuleType.Peek => GetModuleItemsPeek(),
                ModuleType.PowerDisplay => GetModuleItemsPowerDisplay(),
                ModuleType.PowerLauncher => GetModuleItemsPowerLauncher(),
                ModuleType.PowerAccent => GetModuleItemsPowerAccent(),
                ModuleType.Workspaces => GetModuleItemsWorkspaces(),
                ModuleType.GrabAndMove => new ObservableCollection<DashboardModuleItem>(),
                ModuleType.RegistryPreview => GetModuleItemsRegistryPreview(),
                ModuleType.MeasureTool => GetModuleItemsMeasureTool(),
                ModuleType.ShortcutGuide => GetModuleItemsShortcutGuide(),
                ModuleType.PowerOCR => GetModuleItemsPowerOCR(),
                _ => new ObservableCollection<DashboardModuleItem>(), // never called, all values listed above
            };
        }

        private ObservableCollection<DashboardModuleItem> GetModuleItemsAlwaysOnTop()
        {
            ISettingsRepository<AlwaysOnTopSettings> moduleSettingsRepository = SettingsRepository<AlwaysOnTopSettings>.GetInstance(SettingsUtils.Default);
            var list = new List<DashboardModuleItem>
            {
                new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("AlwaysOnTop_ActivationShortcut/Header"), Shortcut = moduleSettingsRepository.SettingsConfig.Properties.Hotkey.Value.GetKeysList() },
                new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("AlwaysOnTop_IncreaseOpacityShortcut/Header"), Shortcut = moduleSettingsRepository.SettingsConfig.Properties.IncreaseOpacityHotkey.Value.GetKeysList() },
                new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("AlwaysOnTop_DecreaseOpacityShortcut/Header"), Shortcut = moduleSettingsRepository.SettingsConfig.Properties.DecreaseOpacityHotkey.Value.GetKeysList() },
            };
            return new ObservableCollection<DashboardModuleItem>(list);
        }

        private ObservableCollection<DashboardModuleItem> GetModuleItemsCmdPal()
        {
            var hotkey = new CmdPalProperties().Hotkey;

            var list = new List<DashboardModuleItem>
            {
                new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("CmdPal_ActivationDescription"), Shortcut = hotkey.GetKeysList() },
            };
            return new ObservableCollection<DashboardModuleItem>(list);
        }

        private ObservableCollection<DashboardModuleItem> GetModuleItemsColorPicker()
        {
            ISettingsRepository<ColorPickerSettings> moduleSettingsRepository = SettingsRepository<ColorPickerSettings>.GetInstance(SettingsUtils.Default);
            var settings = moduleSettingsRepository.SettingsConfig;
            var hotkey = settings.Properties.ActivationShortcut;
            var list = new List<DashboardModuleItem>
            {
                new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("ColorPicker_ShortDescription"), Shortcut = hotkey.GetKeysList() },
            };
            return new ObservableCollection<DashboardModuleItem>(list);
        }

        private ObservableCollection<DashboardModuleItem> GetModuleItemsLightSwitch()
        {
            ISettingsRepository<LightSwitchSettings> moduleSettingsRepository = SettingsRepository<LightSwitchSettings>.GetInstance(SettingsUtils.Default);
            var settings = moduleSettingsRepository.SettingsConfig;
            var list = new List<DashboardModuleItem>
            {
                new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("LightSwitch_ForceDarkMode"), Shortcut = settings.Properties.ToggleThemeHotkey.Value.GetKeysList() },
            };
            return new ObservableCollection<DashboardModuleItem>(list);
        }

        private ObservableCollection<DashboardModuleItem> GetModuleItemsCropAndLock()
        {
            ISettingsRepository<CropAndLockSettings> moduleSettingsRepository = SettingsRepository<CropAndLockSettings>.GetInstance(SettingsUtils.Default);
            var settings = moduleSettingsRepository.SettingsConfig;
            var list = new List<DashboardModuleItem>
            {
                new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("CropAndLock_Thumbnail"), Shortcut = settings.Properties.ThumbnailHotkey.Value.GetKeysList() },
                new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("CropAndLock_Reparent"), Shortcut = settings.Properties.ReparentHotkey.Value.GetKeysList() },
                new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("CropAndLock_Screenshot"), Shortcut = settings.Properties.ScreenshotHotkey.Value.GetKeysList() },
            };
            return new ObservableCollection<DashboardModuleItem>(list);
        }

        private ObservableCollection<DashboardModuleItem> GetModuleItemsEnvironmentVariables()
        {
            var list = new List<DashboardModuleItem>
            {
                new DashboardModuleButtonItem() { ButtonTitle = resourceLoader.GetString("EnvironmentVariables_LaunchButtonControl/Header"), IsButtonDescriptionVisible = true, ButtonDescription = resourceLoader.GetString("EnvironmentVariables_LaunchButtonControl/Description"), ButtonGlyph = "ms-appx:///Assets/Settings/Icons/EnvironmentVariables.png", ButtonClickHandler = EnvironmentVariablesLaunchClicked },
            };
            return new ObservableCollection<DashboardModuleItem>(list);
        }

        private ObservableCollection<DashboardModuleItem> GetModuleItemsFancyZones()
        {
            ISettingsRepository<FancyZonesSettings> moduleSettingsRepository = SettingsRepository<FancyZonesSettings>.GetInstance(SettingsUtils.Default);
            var settings = moduleSettingsRepository.SettingsConfig;
            string activationMode = $"{resourceLoader.GetString(settings.Properties.FancyzonesShiftDrag.Value ? "FancyZones_ActivationShiftDrag" : "FancyZones_ActivationNoShiftDrag")}.";

            var list = new List<DashboardModuleItem>
            {
                new DashboardModuleActivationItem() { Label = resourceLoader.GetString("Activate_Zones"), Activation = activationMode },
                new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("FancyZones_OpenEditor"), Shortcut = settings.Properties.FancyzonesEditorHotkey.Value.GetKeysList() },
                new DashboardModuleButtonItem() { ButtonTitle = resourceLoader.GetString("FancyZones_LaunchEditorButtonControl/Header"), IsButtonDescriptionVisible = true, ButtonDescription = resourceLoader.GetString("FancyZones_LaunchEditorButtonControl/Description"), ButtonGlyph = "ms-appx:///Assets/Settings/Icons/FancyZones.png", ButtonClickHandler = FancyZoneLaunchClicked },
            };
            return new ObservableCollection<DashboardModuleItem>(list);
        }

        private ObservableCollection<DashboardModuleItem> GetModuleItemsFindMyMouse()
        {
            ISettingsRepository<FindMyMouseSettings> moduleSettingsRepository = SettingsRepository<FindMyMouseSettings>.GetInstance(SettingsUtils.Default);
            string shortDescription = resourceLoader.GetString("FindMyMouse_ShortDescription");
            var settings = moduleSettingsRepository.SettingsConfig;
            var activationMethod = settings.Properties.ActivationMethod.Value;
            var list = new List<DashboardModuleItem>();
            if (activationMethod == 3)
            {
                var hotkey = settings.Properties.ActivationShortcut;
                list.Add(new DashboardModuleShortcutItem() { Label = shortDescription, Shortcut = hotkey.GetKeysList() });
            }
            else
            {
                string activation = string.Empty;
                switch (activationMethod)
                {
                    case 2: activation = resourceLoader.GetString("MouseUtils_FindMyMouse_ActivationShakeMouse/Content"); break;
                    case 1: activation = resourceLoader.GetString("MouseUtils_FindMyMouse_ActivationDoubleRightControlPress/Content"); break;
                    case 0:
                    default: activation = resourceLoader.GetString("MouseUtils_FindMyMouse_ActivationDoubleControlPress/Content"); break;
                }

                list.Add(new DashboardModuleActivationItem() { Label = resourceLoader.GetString("Dashboard_Activation"), Activation = activation });
            }

            return new ObservableCollection<DashboardModuleItem>(list);
        }

        private ObservableCollection<DashboardModuleItem> GetModuleItemsHosts()
        {
            var list = new List<DashboardModuleItem>
            {
                new DashboardModuleButtonItem() { ButtonTitle = resourceLoader.GetString("Hosts_LaunchButtonControl/Header"), IsButtonDescriptionVisible = true, ButtonDescription = resourceLoader.GetString("Hosts_LaunchButtonControl/Description"), ButtonGlyph = "ms-appx:///Assets/Settings/Icons/Hosts.png", ButtonClickHandler = HostLaunchClicked },
            };
            return new ObservableCollection<DashboardModuleItem>(list);
        }

        private ObservableCollection<DashboardModuleItem> GetModuleItemsKeyboardManager()
        {
            ISettingsRepository<KeyboardManagerSettings> moduleSettingsRepository = SettingsRepository<KeyboardManagerSettings>.GetInstance(SettingsUtils.Default);
            var settings = moduleSettingsRepository.SettingsConfig;
            var list = new List<DashboardModuleItem>();

            if (settings.Properties.UseNewEditor)
            {
                list.Add(new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("Dashboard_KeyboardManager_OpenEditor"), Shortcut = settings.Properties.EditorShortcut.GetKeysList() });
            }

            return new ObservableCollection<DashboardModuleItem>(list);
        }

        private ObservableCollection<DashboardModuleItem> GetModuleItemsMouseHighlighter()
        {
            ISettingsRepository<MouseHighlighterSettings> moduleSettingsRepository = SettingsRepository<MouseHighlighterSettings>.GetInstance(SettingsUtils.Default);
            var list = new List<DashboardModuleItem>
            {
                new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("MouseHighlighter_ShortDescription"), Shortcut = moduleSettingsRepository.SettingsConfig.Properties.ActivationShortcut.GetKeysList() },
            };
            return new ObservableCollection<DashboardModuleItem>(list);
        }

        private ObservableCollection<DashboardModuleItem> GetModuleItemsMouseJump()
        {
            ISettingsRepository<MouseJumpSettings> moduleSettingsRepository = SettingsRepository<MouseJumpSettings>.GetInstance(SettingsUtils.Default);
            var list = new List<DashboardModuleItem>
            {
                new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("MouseJump_ShortDescription"), Shortcut = moduleSettingsRepository.SettingsConfig.Properties.ActivationShortcut.GetKeysList() },
            };
            return new ObservableCollection<DashboardModuleItem>(list);
        }

        private ObservableCollection<DashboardModuleItem> GetModuleItemsMousePointerCrosshairs()
        {
            ISettingsRepository<MousePointerCrosshairsSettings> moduleSettingsRepository = SettingsRepository<MousePointerCrosshairsSettings>.GetInstance(SettingsUtils.Default);
            var list = new List<DashboardModuleItem>
            {
                new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("MouseCrosshairs_ShortDescription"), Shortcut = moduleSettingsRepository.SettingsConfig.Properties.ActivationShortcut.GetKeysList() },
            };
            return new ObservableCollection<DashboardModuleItem>(list);
        }

        private ObservableCollection<DashboardModuleItem> GetModuleItemsAdvancedPaste()
        {
            ISettingsRepository<AdvancedPasteSettings> moduleSettingsRepository = SettingsRepository<AdvancedPasteSettings>.GetInstance(SettingsUtils.Default);
            var list = new List<DashboardModuleItem>
            {
                new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("AdvancedPasteUI_Shortcut/Header"), Shortcut = moduleSettingsRepository.SettingsConfig.Properties.AdvancedPasteUIShortcut.GetKeysList() },
                new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("PasteAsPlainText_Shortcut/Header"), Shortcut = moduleSettingsRepository.SettingsConfig.Properties.PasteAsPlainTextShortcut.GetKeysList() },
            };

            if (moduleSettingsRepository.SettingsConfig.Properties.PasteAsMarkdownShortcut.GetKeysList().Count > 0)
            {
                list.Add(new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("PasteAsMarkdown_Shortcut/Header"), Shortcut = moduleSettingsRepository.SettingsConfig.Properties.PasteAsMarkdownShortcut.GetKeysList() });
            }

            if (moduleSettingsRepository.SettingsConfig.Properties.PasteAsJsonShortcut.GetKeysList().Count > 0)
            {
                list.Add(new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("PasteAsJson_Shortcut/Header"), Shortcut = moduleSettingsRepository.SettingsConfig.Properties.PasteAsJsonShortcut.GetKeysList() });
            }

            return new ObservableCollection<DashboardModuleItem>(list);
        }

        private ObservableCollection<DashboardModuleItem> GetModuleItemsPeek()
        {
            ISettingsRepository<PeekSettings> moduleSettingsRepository = SettingsRepository<PeekSettings>.GetInstance(SettingsUtils.Default);
            var list = new List<DashboardModuleItem>
            {
                new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("Peek_ShortDescription"), Shortcut = moduleSettingsRepository.SettingsConfig.Properties.ActivationShortcut.GetKeysList() },
            };
            return new ObservableCollection<DashboardModuleItem>(list);
        }

        private ObservableCollection<DashboardModuleItem> GetModuleItemsPowerLauncher()
        {
            ISettingsRepository<PowerLauncherSettings> moduleSettingsRepository = SettingsRepository<PowerLauncherSettings>.GetInstance(SettingsUtils.Default);
            var list = new List<DashboardModuleItem>
            {
                new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("Run_ShortDescription"), Shortcut = moduleSettingsRepository.SettingsConfig.Properties.OpenPowerLauncher.GetKeysList() },
            };
            return new ObservableCollection<DashboardModuleItem>(list);
        }

        private ObservableCollection<DashboardModuleItem> GetModuleItemsPowerAccent()
        {
            var settingsUtils = SettingsUtils.Default;
            PowerAccentSettings moduleSettings = settingsUtils.GetSettingsOrDefault<PowerAccentSettings>(PowerAccentSettings.ModuleName);
            var activationMethod = moduleSettings.Properties.ActivationKey;
            string activation = string.Empty;
            switch (activationMethod)
            {
                case Library.Enumerations.PowerAccentActivationKey.LeftRightArrow: activation = resourceLoader.GetString("QuickAccent_Activation_Key_Arrows/Content"); break;
                case Library.Enumerations.PowerAccentActivationKey.Space: activation = resourceLoader.GetString("QuickAccent_Activation_Key_Space/Content"); break;
                case Library.Enumerations.PowerAccentActivationKey.Both: activation = resourceLoader.GetString("QuickAccent_Activation_Key_Either/Content"); break;
            }

            var list = new List<DashboardModuleItem>
            {
                new DashboardModuleActivationItem() { Label = resourceLoader.GetString("Dashboard_Activation"), Activation = activation },
            };
            return new ObservableCollection<DashboardModuleItem>(list);
        }

        private ObservableCollection<DashboardModuleItem> GetModuleItemsWorkspaces()
        {
            ISettingsRepository<WorkspacesSettings> moduleSettingsRepository = SettingsRepository<WorkspacesSettings>.GetInstance(SettingsUtils.Default);
            var settings = moduleSettingsRepository.SettingsConfig;

            var list = new List<DashboardModuleItem>
            {
                new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("Workspaces_ShortDescription"), Shortcut = settings.Properties.Hotkey.Value.GetKeysList() },
                new DashboardModuleButtonItem() { ButtonTitle = resourceLoader.GetString("Workspaces_LaunchEditorButtonControl/Header"), IsButtonDescriptionVisible = true, ButtonDescription = resourceLoader.GetString("FancyZones_LaunchEditorButtonControl/Description"), ButtonGlyph = "ms-appx:///Assets/Settings/Icons/Workspaces.png", ButtonClickHandler = WorkspacesLaunchClicked },
            };
            return new ObservableCollection<DashboardModuleItem>(list);
        }

        private ObservableCollection<DashboardModuleItem> GetModuleItemsRegistryPreview()
        {
            var list = new List<DashboardModuleItem>
            {
                new DashboardModuleButtonItem() { ButtonTitle = resourceLoader.GetString("RegistryPreview_LaunchButtonControl/Header"), ButtonGlyph = "ms-appx:///Assets/Settings/Icons/RegistryPreview.png",  ButtonClickHandler = RegistryPreviewLaunchClicked },
            };
            return new ObservableCollection<DashboardModuleItem>(list);
        }

        private ObservableCollection<DashboardModuleItem> GetModuleItemsMeasureTool()
        {
            ISettingsRepository<MeasureToolSettings> moduleSettingsRepository = SettingsRepository<MeasureToolSettings>.GetInstance(SettingsUtils.Default);
            var list = new List<DashboardModuleItem>
            {
                new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("ScreenRuler_ShortDescription"), Shortcut = moduleSettingsRepository.SettingsConfig.Properties.ActivationShortcut.GetKeysList() },
            };
            return new ObservableCollection<DashboardModuleItem>(list);
        }

        private ObservableCollection<DashboardModuleItem> GetModuleItemsShortcutGuide()
        {
            ISettingsRepository<ShortcutGuideSettings> moduleSettingsRepository = SettingsRepository<ShortcutGuideSettings>.GetInstance(SettingsUtils.Default);

            var shortcut = moduleSettingsRepository.SettingsConfig.Properties.UseLegacyPressWinKeyBehavior.Value
                ? new List<object> { 92 } // Right Windows key code
                : moduleSettingsRepository.SettingsConfig.Properties.OpenShortcutGuide.GetKeysList();

            var list = new List<DashboardModuleItem>
            {
                new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("ShortcutGuide_ShortDescription"), Shortcut = shortcut },
            };
            return new ObservableCollection<DashboardModuleItem>(list);
        }

        private ObservableCollection<DashboardModuleItem> GetModuleItemsPowerOCR()
        {
            ISettingsRepository<PowerOcrSettings> moduleSettingsRepository = SettingsRepository<PowerOcrSettings>.GetInstance(SettingsUtils.Default);
            var list = new List<DashboardModuleItem>
            {
                new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("PowerOcr_ShortDescription"), Shortcut = moduleSettingsRepository.SettingsConfig.Properties.ActivationShortcut.GetKeysList() },
            };
            return new ObservableCollection<DashboardModuleItem>(list);
        }

        private ObservableCollection<DashboardModuleItem> GetModuleItemsPowerDisplay()
        {
            ISettingsRepository<PowerDisplaySettings> moduleSettingsRepository = SettingsRepository<PowerDisplaySettings>.GetInstance(SettingsUtils.Default);
            var settings = moduleSettingsRepository.SettingsConfig;
            var list = new List<DashboardModuleItem>
            {
                new DashboardModuleShortcutItem() { Label = resourceLoader.GetString("PowerDisplay_ToggleWindow"), Shortcut = settings.Properties.ActivationShortcut.GetKeysList() },
                new DashboardModuleButtonItem() { ButtonTitle = resourceLoader.GetString("PowerDisplay_LaunchButtonControl/Header"), IsButtonDescriptionVisible = true, ButtonDescription = resourceLoader.GetString("PowerDisplay_LaunchButtonControl/Description"), ButtonGlyph = "ms-appx:///Assets/Settings/Icons/PowerDisplay.png", ButtonClickHandler = PowerDisplayLaunchClicked },
            };
            return new ObservableCollection<DashboardModuleItem>(list);
        }

        internal void SWVersionButtonClicked()
        {
            NavigationService.Navigate(typeof(GeneralPage));
        }

        private void EnvironmentVariablesLaunchClicked(object sender, RoutedEventArgs e)
        {
            var settingsUtils = SettingsUtils.Default;
            var environmentVariablesViewModel = new EnvironmentVariablesViewModel(settingsUtils, SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), SettingsRepository<EnvironmentVariablesSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage, App.IsElevated);
            environmentVariablesViewModel.Launch();
        }

        private void HostLaunchClicked(object sender, RoutedEventArgs e)
        {
            var settingsUtils = SettingsUtils.Default;
            var hostsViewModel = new HostsViewModel(settingsUtils, SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), SettingsRepository<HostsSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage, App.IsElevated);
            hostsViewModel.Launch();
        }

        private void FancyZoneLaunchClicked(object sender, RoutedEventArgs e)
        {
            // send message to launch the zones editor;
            SendConfigMSG("{\"action\":{\"FancyZones\":{\"action_name\":\"ToggledFZEditor\", \"value\":\"\"}}}");
        }

        private void WorkspacesLaunchClicked(object sender, RoutedEventArgs e)
        {
            // send message to launch the Workspaces editor;
            SendConfigMSG("{\"action\":{\"Workspaces\":{\"action_name\":\"LaunchEditor\", \"value\":\"\"}}}");
        }

        private void RegistryPreviewLaunchClicked(object sender, RoutedEventArgs e)
        {
            var actionName = "Launch";
            SendConfigMSG("{\"action\":{\"RegistryPreview\":{\"action_name\":\"" + actionName + "\", \"value\":\"\"}}}");
        }

        private void PowerDisplayLaunchClicked(object sender, RoutedEventArgs e)
        {
            var actionName = "Launch";
            SendConfigMSG("{\"action\":{\"PowerDisplay\":{\"action_name\":\"" + actionName + "\", \"value\":\"\"}}}");
        }

        internal void DashboardListItemClick(object sender)
        {
            if (sender is ModuleType moduleType)
            {
                NavigationService.Navigate(ModuleGpoHelper.GetModulePageType(moduleType));
            }
        }

        public override void Dispose()
        {
            if (_isDisposed)
            {
                return;
            }

            _isDisposed = true;
            base.Dispose();
            if (_settingsRepository != null)
            {
                _settingsRepository.SettingsChanged -= OnSettingsChanged;
            }

            GC.SuppressFinalize(this);
        }
    }
}
