// 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.ComponentModel;
using System.Runtime.CompilerServices;
using global::PowerToys.GPOWrapper;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
using Microsoft.PowerToys.Settings.Utilities;

namespace Microsoft.PowerToys.Settings.UI.ViewModels
{
    public class MouseUtilsViewModel : Observable
    {
        private ISettingsUtils SettingsUtils { get; set; }

        private GeneralSettings GeneralSettingsConfig { get; set; }

        private FindMyMouseSettings FindMyMouseSettingsConfig { get; set; }

        private MouseHighlighterSettings MouseHighlighterSettingsConfig { get; set; }

        private MouseJumpSettings MouseJumpSettingsConfig { get; set; }

        private MousePointerCrosshairsSettings MousePointerCrosshairsSettingsConfig { get; set; }

        public MouseUtilsViewModel(ISettingsUtils settingsUtils, ISettingsRepository<GeneralSettings> settingsRepository, ISettingsRepository<FindMyMouseSettings> findMyMouseSettingsRepository, ISettingsRepository<MouseHighlighterSettings> mouseHighlighterSettingsRepository, ISettingsRepository<MouseJumpSettings> mouseJumpSettingsRepository, ISettingsRepository<MousePointerCrosshairsSettings> mousePointerCrosshairsSettingsRepository, Func<string, int> ipcMSGCallBackFunc)
        {
            SettingsUtils = settingsUtils;

            // To obtain the general settings configurations of PowerToys Settings.
            ArgumentNullException.ThrowIfNull(settingsRepository);

            GeneralSettingsConfig = settingsRepository.SettingsConfig;

            InitializeEnabledValues();

            // To obtain the find my mouse settings, if the file exists.
            // If not, to create a file with the default settings and to return the default configurations.
            ArgumentNullException.ThrowIfNull(findMyMouseSettingsRepository);

            FindMyMouseSettingsConfig = findMyMouseSettingsRepository.SettingsConfig;
            _findMyMouseActivationMethod = FindMyMouseSettingsConfig.Properties.ActivationMethod.Value < 4 ? FindMyMouseSettingsConfig.Properties.ActivationMethod.Value : 0;
            _findMyMouseDoNotActivateOnGameMode = FindMyMouseSettingsConfig.Properties.DoNotActivateOnGameMode.Value;

            string backgroundColor = FindMyMouseSettingsConfig.Properties.BackgroundColor.Value;
            _findMyMouseBackgroundColor = !string.IsNullOrEmpty(backgroundColor) ? backgroundColor : "#000000";

            string spotlightColor = FindMyMouseSettingsConfig.Properties.SpotlightColor.Value;
            _findMyMouseSpotlightColor = !string.IsNullOrEmpty(spotlightColor) ? spotlightColor : "#FFFFFF";

            _findMyMouseOverlayOpacity = FindMyMouseSettingsConfig.Properties.OverlayOpacity.Value;
            _findMyMouseSpotlightRadius = FindMyMouseSettingsConfig.Properties.SpotlightRadius.Value;
            _findMyMouseAnimationDurationMs = FindMyMouseSettingsConfig.Properties.AnimationDurationMs.Value;
            _findMyMouseSpotlightInitialZoom = FindMyMouseSettingsConfig.Properties.SpotlightInitialZoom.Value;
            _findMyMouseExcludedApps = FindMyMouseSettingsConfig.Properties.ExcludedApps.Value;
            _findMyMouseShakingMinimumDistance = FindMyMouseSettingsConfig.Properties.ShakingMinimumDistance.Value;
            _findMyMouseShakingIntervalMs = FindMyMouseSettingsConfig.Properties.ShakingIntervalMs.Value;
            _findMyMouseShakingFactor = FindMyMouseSettingsConfig.Properties.ShakingFactor.Value;

            ArgumentNullException.ThrowIfNull(mouseHighlighterSettingsRepository);

            MouseHighlighterSettingsConfig = mouseHighlighterSettingsRepository.SettingsConfig;
            string leftClickColor = MouseHighlighterSettingsConfig.Properties.LeftButtonClickColor.Value;
            _highlighterLeftButtonClickColor = !string.IsNullOrEmpty(leftClickColor) ? leftClickColor : "#a6FFFF00";

            string rightClickColor = MouseHighlighterSettingsConfig.Properties.RightButtonClickColor.Value;
            _highlighterRightButtonClickColor = !string.IsNullOrEmpty(rightClickColor) ? rightClickColor : "#a60000FF";

            string alwaysColor = MouseHighlighterSettingsConfig.Properties.AlwaysColor.Value;
            _highlighterAlwaysColor = !string.IsNullOrEmpty(alwaysColor) ? alwaysColor : "#00FF0000";

            _highlighterRadius = MouseHighlighterSettingsConfig.Properties.HighlightRadius.Value;
            _highlightFadeDelayMs = MouseHighlighterSettingsConfig.Properties.HighlightFadeDelayMs.Value;
            _highlightFadeDurationMs = MouseHighlighterSettingsConfig.Properties.HighlightFadeDurationMs.Value;
            _highlighterAutoActivate = MouseHighlighterSettingsConfig.Properties.AutoActivate.Value;

            ArgumentNullException.ThrowIfNull(mouseJumpSettingsRepository);

            MouseJumpSettingsConfig = mouseJumpSettingsRepository.SettingsConfig;
            MouseJumpSettingsConfig.Properties.ThumbnailSize.PropertyChanged += MouseJumpThumbnailSizePropertyChanged;

            ArgumentNullException.ThrowIfNull(mousePointerCrosshairsSettingsRepository);

            MousePointerCrosshairsSettingsConfig = mousePointerCrosshairsSettingsRepository.SettingsConfig;

            string crosshairsColor = MousePointerCrosshairsSettingsConfig.Properties.CrosshairsColor.Value;
            _mousePointerCrosshairsColor = !string.IsNullOrEmpty(crosshairsColor) ? crosshairsColor : "#FF0000";

            string crosshairsBorderColor = MousePointerCrosshairsSettingsConfig.Properties.CrosshairsBorderColor.Value;
            _mousePointerCrosshairsBorderColor = !string.IsNullOrEmpty(crosshairsBorderColor) ? crosshairsBorderColor : "#FFFFFF";

            _mousePointerCrosshairsOpacity = MousePointerCrosshairsSettingsConfig.Properties.CrosshairsOpacity.Value;
            _mousePointerCrosshairsRadius = MousePointerCrosshairsSettingsConfig.Properties.CrosshairsRadius.Value;
            _mousePointerCrosshairsThickness = MousePointerCrosshairsSettingsConfig.Properties.CrosshairsThickness.Value;
            _mousePointerCrosshairsBorderSize = MousePointerCrosshairsSettingsConfig.Properties.CrosshairsBorderSize.Value;
            _mousePointerCrosshairsAutoHide = MousePointerCrosshairsSettingsConfig.Properties.CrosshairsAutoHide.Value;
            _mousePointerCrosshairsIsFixedLengthEnabled = MousePointerCrosshairsSettingsConfig.Properties.CrosshairsIsFixedLengthEnabled.Value;
            _mousePointerCrosshairsFixedLength = MousePointerCrosshairsSettingsConfig.Properties.CrosshairsFixedLength.Value;
            _mousePointerCrosshairsAutoActivate = MousePointerCrosshairsSettingsConfig.Properties.AutoActivate.Value;

            int isEnabled = 0;
            NativeMethods.SystemParametersInfo(NativeMethods.SPI_GETCLIENTAREAANIMATION, 0, ref isEnabled, 0);
            _isAnimationEnabledBySystem = isEnabled != 0;

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

        private void InitializeEnabledValues()
        {
            _findMyMouseEnabledGpoRuleConfiguration = GPOWrapper.GetConfiguredFindMyMouseEnabledValue();
            if (_findMyMouseEnabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _findMyMouseEnabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
            {
                // Get the enabled state from GPO.
                _findMyMouseEnabledStateIsGPOConfigured = true;
                _isFindMyMouseEnabled = _findMyMouseEnabledGpoRuleConfiguration == GpoRuleConfigured.Enabled;
            }
            else
            {
                _isFindMyMouseEnabled = GeneralSettingsConfig.Enabled.FindMyMouse;
            }

            _highlighterEnabledGpoRuleConfiguration = GPOWrapper.GetConfiguredMouseHighlighterEnabledValue();
            if (_highlighterEnabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _highlighterEnabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
            {
                // Get the enabled state from GPO.
                _highlighterEnabledStateIsGPOConfigured = true;
                _isMouseHighlighterEnabled = _highlighterEnabledGpoRuleConfiguration == GpoRuleConfigured.Enabled;
            }
            else
            {
                _isMouseHighlighterEnabled = GeneralSettingsConfig.Enabled.MouseHighlighter;
            }

            _jumpEnabledGpoRuleConfiguration = GPOWrapper.GetConfiguredMouseJumpEnabledValue();
            if (_jumpEnabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _jumpEnabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
            {
                // Get the enabled state from GPO.
                _jumpEnabledStateIsGPOConfigured = true;
                _isMouseJumpEnabled = _jumpEnabledGpoRuleConfiguration == GpoRuleConfigured.Enabled;
            }
            else
            {
                _isMouseJumpEnabled = GeneralSettingsConfig.Enabled.MouseJump;
            }

            _mousePointerCrosshairsEnabledGpoRuleConfiguration = GPOWrapper.GetConfiguredMousePointerCrosshairsEnabledValue();
            if (_mousePointerCrosshairsEnabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _mousePointerCrosshairsEnabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
            {
                // Get the enabled state from GPO.
                _mousePointerCrosshairsEnabledStateIsGPOConfigured = true;
                _isMousePointerCrosshairsEnabled = _mousePointerCrosshairsEnabledGpoRuleConfiguration == GpoRuleConfigured.Enabled;
            }
            else
            {
                _isMousePointerCrosshairsEnabled = GeneralSettingsConfig.Enabled.MousePointerCrosshairs;
            }
        }

        public bool IsFindMyMouseEnabled
        {
            get => _isFindMyMouseEnabled;
            set
            {
                if (_findMyMouseEnabledStateIsGPOConfigured)
                {
                    // If it's GPO configured, shouldn't be able to change this state.
                    return;
                }

                if (_isFindMyMouseEnabled != value)
                {
                    _isFindMyMouseEnabled = value;

                    GeneralSettingsConfig.Enabled.FindMyMouse = value;
                    OnPropertyChanged(nameof(IsFindMyMouseEnabled));

                    OutGoingGeneralSettings outgoing = new OutGoingGeneralSettings(GeneralSettingsConfig);
                    SendConfigMSG(outgoing.ToString());

                    NotifyFindMyMousePropertyChanged();
                }
            }
        }

        public bool IsFindMyMouseEnabledGpoConfigured
        {
            get => _findMyMouseEnabledStateIsGPOConfigured;
        }

        public int FindMyMouseActivationMethod
        {
            get
            {
                return _findMyMouseActivationMethod;
            }

            set
            {
                if (value != _findMyMouseActivationMethod)
                {
                    _findMyMouseActivationMethod = value;
                    FindMyMouseSettingsConfig.Properties.ActivationMethod.Value = value;
                    NotifyFindMyMousePropertyChanged();
                }
            }
        }

        public HotkeySettings FindMyMouseActivationShortcut
        {
            get
            {
                return FindMyMouseSettingsConfig.Properties.ActivationShortcut;
            }

            set
            {
                if (FindMyMouseSettingsConfig.Properties.ActivationShortcut != value)
                {
                    FindMyMouseSettingsConfig.Properties.ActivationShortcut = value ?? FindMyMouseSettingsConfig.Properties.DefaultActivationShortcut;
                    NotifyFindMyMousePropertyChanged();
                }
            }
        }

        public bool FindMyMouseDoNotActivateOnGameMode
        {
            get
            {
                return _findMyMouseDoNotActivateOnGameMode;
            }

            set
            {
                if (_findMyMouseDoNotActivateOnGameMode != value)
                {
                    _findMyMouseDoNotActivateOnGameMode = value;
                    FindMyMouseSettingsConfig.Properties.DoNotActivateOnGameMode.Value = value;
                    NotifyFindMyMousePropertyChanged();
                }
            }
        }

        public string FindMyMouseBackgroundColor
        {
            get
            {
                return _findMyMouseBackgroundColor;
            }

            set
            {
                value = (value != null) ? SettingsUtilities.ToRGBHex(value) : "#000000";
                if (!value.Equals(_findMyMouseBackgroundColor, StringComparison.OrdinalIgnoreCase))
                {
                    _findMyMouseBackgroundColor = value;
                    FindMyMouseSettingsConfig.Properties.BackgroundColor.Value = value;
                    NotifyFindMyMousePropertyChanged();
                }
            }
        }

        public string FindMyMouseSpotlightColor
        {
            get
            {
                return _findMyMouseSpotlightColor;
            }

            set
            {
                value = (value != null) ? SettingsUtilities.ToRGBHex(value) : "#FFFFFF";
                if (!value.Equals(_findMyMouseSpotlightColor, StringComparison.OrdinalIgnoreCase))
                {
                    _findMyMouseSpotlightColor = value;
                    FindMyMouseSettingsConfig.Properties.SpotlightColor.Value = value;
                    NotifyFindMyMousePropertyChanged();
                }
            }
        }

        public int FindMyMouseOverlayOpacity
        {
            get
            {
                return _findMyMouseOverlayOpacity;
            }

            set
            {
                if (value != _findMyMouseOverlayOpacity)
                {
                    _findMyMouseOverlayOpacity = value;
                    FindMyMouseSettingsConfig.Properties.OverlayOpacity.Value = value;
                    NotifyFindMyMousePropertyChanged();
                }
            }
        }

        public int FindMyMouseSpotlightRadius
        {
            get
            {
                return _findMyMouseSpotlightRadius;
            }

            set
            {
                if (value != _findMyMouseSpotlightRadius)
                {
                    _findMyMouseSpotlightRadius = value;
                    FindMyMouseSettingsConfig.Properties.SpotlightRadius.Value = value;
                    NotifyFindMyMousePropertyChanged();
                }
            }
        }

        public bool IsAnimationEnabledBySystem
        {
            get
            {
                return _isAnimationEnabledBySystem;
            }

            set
            {
                _isAnimationEnabledBySystem = value;
            }
        }

        public int FindMyMouseAnimationDurationMs
        {
            get
            {
                return _findMyMouseAnimationDurationMs;
            }

            set
            {
                if (value != _findMyMouseAnimationDurationMs)
                {
                    _findMyMouseAnimationDurationMs = value;
                    FindMyMouseSettingsConfig.Properties.AnimationDurationMs.Value = value;
                    NotifyFindMyMousePropertyChanged();
                }
            }
        }

        public int FindMyMouseSpotlightInitialZoom
        {
            get
            {
                return _findMyMouseSpotlightInitialZoom;
            }

            set
            {
                if (value != _findMyMouseSpotlightInitialZoom)
                {
                    _findMyMouseSpotlightInitialZoom = value;
                    FindMyMouseSettingsConfig.Properties.SpotlightInitialZoom.Value = value;
                    NotifyFindMyMousePropertyChanged();
                }
            }
        }

        public string FindMyMouseExcludedApps
        {
            get
            {
                return _findMyMouseExcludedApps;
            }

            set
            {
                if (value != _findMyMouseExcludedApps)
                {
                    _findMyMouseExcludedApps = value;
                    FindMyMouseSettingsConfig.Properties.ExcludedApps.Value = value;
                    NotifyFindMyMousePropertyChanged();
                }
            }
        }

        public int FindMyMouseShakingMinimumDistance
        {
            get
            {
                return _findMyMouseShakingMinimumDistance;
            }

            set
            {
                if (value != _findMyMouseShakingMinimumDistance)
                {
                    _findMyMouseShakingMinimumDistance = value;
                    FindMyMouseSettingsConfig.Properties.ShakingMinimumDistance.Value = value;
                    NotifyFindMyMousePropertyChanged();
                }
            }
        }

        public int FindMyMouseShakingIntervalMs
        {
            get
            {
                return _findMyMouseShakingIntervalMs;
            }

            set
            {
                if (value != _findMyMouseShakingIntervalMs)
                {
                    _findMyMouseShakingIntervalMs = value;
                    FindMyMouseSettingsConfig.Properties.ShakingIntervalMs.Value = value;
                    NotifyFindMyMousePropertyChanged();
                }
            }
        }

        public int FindMyMouseShakingFactor
        {
            get
            {
                return _findMyMouseShakingFactor;
            }

            set
            {
                if (value != _findMyMouseShakingFactor)
                {
                    _findMyMouseShakingFactor = value;
                    FindMyMouseSettingsConfig.Properties.ShakingFactor.Value = value;
                    NotifyFindMyMousePropertyChanged();
                }
            }
        }

        public void NotifyFindMyMousePropertyChanged([CallerMemberName] string propertyName = null)
        {
            OnPropertyChanged(propertyName);

            SndFindMyMouseSettings outsettings = new SndFindMyMouseSettings(FindMyMouseSettingsConfig);
            SndModuleSettings<SndFindMyMouseSettings> ipcMessage = new SndModuleSettings<SndFindMyMouseSettings>(outsettings);
            SendConfigMSG(ipcMessage.ToJsonString());
            SettingsUtils.SaveSettings(FindMyMouseSettingsConfig.ToJsonString(), FindMyMouseSettings.ModuleName);
        }

        public bool IsMouseHighlighterEnabled
        {
            get => _isMouseHighlighterEnabled;
            set
            {
                if (_highlighterEnabledStateIsGPOConfigured)
                {
                    // If it's GPO configured, shouldn't be able to change this state.
                    return;
                }

                if (_isMouseHighlighterEnabled != value)
                {
                    _isMouseHighlighterEnabled = value;

                    GeneralSettingsConfig.Enabled.MouseHighlighter = value;
                    OnPropertyChanged(nameof(_isMouseHighlighterEnabled));

                    OutGoingGeneralSettings outgoing = new OutGoingGeneralSettings(GeneralSettingsConfig);
                    SendConfigMSG(outgoing.ToString());

                    NotifyMouseHighlighterPropertyChanged();
                }
            }
        }

        public bool IsHighlighterEnabledGpoConfigured
        {
            get => _highlighterEnabledStateIsGPOConfigured;
        }

        public HotkeySettings MouseHighlighterActivationShortcut
        {
            get
            {
                return MouseHighlighterSettingsConfig.Properties.ActivationShortcut;
            }

            set
            {
                if (MouseHighlighterSettingsConfig.Properties.ActivationShortcut != value)
                {
                    MouseHighlighterSettingsConfig.Properties.ActivationShortcut = value ?? MouseHighlighterSettingsConfig.Properties.DefaultActivationShortcut;
                    NotifyMouseHighlighterPropertyChanged();
                }
            }
        }

        public string MouseHighlighterLeftButtonClickColor
        {
            get
            {
                return _highlighterLeftButtonClickColor;
            }

            set
            {
                value = SettingsUtilities.ToARGBHex(value);
                if (!value.Equals(_highlighterLeftButtonClickColor, StringComparison.OrdinalIgnoreCase))
                {
                    _highlighterLeftButtonClickColor = value;
                    MouseHighlighterSettingsConfig.Properties.LeftButtonClickColor.Value = value;
                    NotifyMouseHighlighterPropertyChanged();
                }
            }
        }

        public string MouseHighlighterRightButtonClickColor
        {
            get
            {
                return _highlighterRightButtonClickColor;
            }

            set
            {
                value = SettingsUtilities.ToARGBHex(value);
                if (!value.Equals(_highlighterRightButtonClickColor, StringComparison.OrdinalIgnoreCase))
                {
                    _highlighterRightButtonClickColor = value;
                    MouseHighlighterSettingsConfig.Properties.RightButtonClickColor.Value = value;
                    NotifyMouseHighlighterPropertyChanged();
                }
            }
        }

        public string MouseHighlighterAlwaysColor
        {
            get
            {
                return _highlighterAlwaysColor;
            }

            set
            {
                value = SettingsUtilities.ToARGBHex(value);
                if (!value.Equals(_highlighterAlwaysColor, StringComparison.OrdinalIgnoreCase))
                {
                    _highlighterAlwaysColor = value;
                    MouseHighlighterSettingsConfig.Properties.AlwaysColor.Value = value;
                    NotifyMouseHighlighterPropertyChanged();
                }
            }
        }

        public int MouseHighlighterRadius
        {
            get
            {
                return _highlighterRadius;
            }

            set
            {
                if (value != _highlighterRadius)
                {
                    _highlighterRadius = value;
                    MouseHighlighterSettingsConfig.Properties.HighlightRadius.Value = value;
                    NotifyMouseHighlighterPropertyChanged();
                }
            }
        }

        public int MouseHighlighterFadeDelayMs
        {
            get
            {
                return _highlightFadeDelayMs;
            }

            set
            {
                if (value != _highlightFadeDelayMs)
                {
                    _highlightFadeDelayMs = value;
                    MouseHighlighterSettingsConfig.Properties.HighlightFadeDelayMs.Value = value;
                    NotifyMouseHighlighterPropertyChanged();
                }
            }
        }

        public int MouseHighlighterFadeDurationMs
        {
            get
            {
                return _highlightFadeDurationMs;
            }

            set
            {
                if (value != _highlightFadeDurationMs)
                {
                    _highlightFadeDurationMs = value;
                    MouseHighlighterSettingsConfig.Properties.HighlightFadeDurationMs.Value = value;
                    NotifyMouseHighlighterPropertyChanged();
                }
            }
        }

        public bool MouseHighlighterAutoActivate
        {
            get
            {
                return _highlighterAutoActivate;
            }

            set
            {
                if (value != _highlighterAutoActivate)
                {
                    _highlighterAutoActivate = value;
                    MouseHighlighterSettingsConfig.Properties.AutoActivate.Value = value;
                    NotifyMouseHighlighterPropertyChanged();
                }
            }
        }

        public void NotifyMouseHighlighterPropertyChanged([CallerMemberName] string propertyName = null)
        {
            OnPropertyChanged(propertyName);

            SndMouseHighlighterSettings outsettings = new SndMouseHighlighterSettings(MouseHighlighterSettingsConfig);
            SndModuleSettings<SndMouseHighlighterSettings> ipcMessage = new SndModuleSettings<SndMouseHighlighterSettings>(outsettings);
            SendConfigMSG(ipcMessage.ToJsonString());
            SettingsUtils.SaveSettings(MouseHighlighterSettingsConfig.ToJsonString(), MouseHighlighterSettings.ModuleName);
        }

        public bool IsMouseJumpEnabled
        {
            get => _isMouseJumpEnabled;
            set
            {
                if (_jumpEnabledStateIsGPOConfigured)
                {
                    // If it's GPO configured, shouldn't be able to change this state.
                    return;
                }

                if (_isMouseJumpEnabled != value)
                {
                    _isMouseJumpEnabled = value;

                    GeneralSettingsConfig.Enabled.MouseJump = value;
                    OnPropertyChanged(nameof(_isMouseJumpEnabled));

                    OutGoingGeneralSettings outgoing = new OutGoingGeneralSettings(GeneralSettingsConfig);
                    SendConfigMSG(outgoing.ToString());

                    NotifyMouseJumpPropertyChanged();
                }
            }
        }

        public bool IsJumpEnabledGpoConfigured
        {
            get => _jumpEnabledStateIsGPOConfigured;
        }

        public HotkeySettings MouseJumpActivationShortcut
        {
            get
            {
                return MouseJumpSettingsConfig.Properties.ActivationShortcut;
            }

            set
            {
                if (MouseJumpSettingsConfig.Properties.ActivationShortcut != value)
                {
                    MouseJumpSettingsConfig.Properties.ActivationShortcut = value ?? MouseJumpSettingsConfig.Properties.DefaultActivationShortcut;
                    NotifyMouseJumpPropertyChanged();
                }
            }
        }

        public MouseJumpThumbnailSize MouseJumpThumbnailSize
        {
            get
            {
                return MouseJumpSettingsConfig.Properties.ThumbnailSize;
            }

            set
            {
                if ((MouseJumpSettingsConfig.Properties.ThumbnailSize.Width != value?.Width)
                    && (MouseJumpSettingsConfig.Properties.ThumbnailSize.Height != value?.Height))
                {
                    MouseJumpSettingsConfig.Properties.ThumbnailSize = value;
                    NotifyMouseJumpPropertyChanged();
                }
            }
        }

        public void MouseJumpThumbnailSizePropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            NotifyMouseJumpPropertyChanged(nameof(MouseJumpThumbnailSize));
        }

        public void NotifyMouseJumpPropertyChanged([CallerMemberName] string propertyName = null)
        {
            OnPropertyChanged(propertyName);

            SndMouseJumpSettings outsettings = new SndMouseJumpSettings(MouseJumpSettingsConfig);
            SndModuleSettings<SndMouseJumpSettings> ipcMessage = new SndModuleSettings<SndMouseJumpSettings>(outsettings);
            SendConfigMSG(ipcMessage.ToJsonString());
            SettingsUtils.SaveSettings(MouseJumpSettingsConfig.ToJsonString(), MouseJumpSettings.ModuleName);
        }

        public bool IsMousePointerCrosshairsEnabled
        {
            get => _isMousePointerCrosshairsEnabled;
            set
            {
                if (_mousePointerCrosshairsEnabledStateIsGPOConfigured)
                {
                    // If it's GPO configured, shouldn't be able to change this state.
                    return;
                }

                if (_isMousePointerCrosshairsEnabled != value)
                {
                    _isMousePointerCrosshairsEnabled = value;

                    GeneralSettingsConfig.Enabled.MousePointerCrosshairs = value;
                    OnPropertyChanged(nameof(_isMousePointerCrosshairsEnabled));

                    OutGoingGeneralSettings outgoing = new OutGoingGeneralSettings(GeneralSettingsConfig);
                    SendConfigMSG(outgoing.ToString());

                    NotifyMousePointerCrosshairsPropertyChanged();
                }
            }
        }

        public bool IsMousePointerCrosshairsEnabledGpoConfigured
        {
            get => _mousePointerCrosshairsEnabledStateIsGPOConfigured;
        }

        public HotkeySettings MousePointerCrosshairsActivationShortcut
        {
            get
            {
                return MousePointerCrosshairsSettingsConfig.Properties.ActivationShortcut;
            }

            set
            {
                if (MousePointerCrosshairsSettingsConfig.Properties.ActivationShortcut != value)
                {
                    MousePointerCrosshairsSettingsConfig.Properties.ActivationShortcut = value ?? MousePointerCrosshairsSettingsConfig.Properties.DefaultActivationShortcut;
                    NotifyMousePointerCrosshairsPropertyChanged();
                }
            }
        }

        public string MousePointerCrosshairsColor
        {
            get
            {
                return _mousePointerCrosshairsColor;
            }

            set
            {
                value = SettingsUtilities.ToRGBHex(value);
                if (!value.Equals(_mousePointerCrosshairsColor, StringComparison.OrdinalIgnoreCase))
                {
                    _mousePointerCrosshairsColor = value;
                    MousePointerCrosshairsSettingsConfig.Properties.CrosshairsColor.Value = value;
                    NotifyMousePointerCrosshairsPropertyChanged();
                }
            }
        }

        public int MousePointerCrosshairsOpacity
        {
            get
            {
                return _mousePointerCrosshairsOpacity;
            }

            set
            {
                if (value != _mousePointerCrosshairsOpacity)
                {
                    _mousePointerCrosshairsOpacity = value;
                    MousePointerCrosshairsSettingsConfig.Properties.CrosshairsOpacity.Value = value;
                    NotifyMousePointerCrosshairsPropertyChanged();
                }
            }
        }

        public int MousePointerCrosshairsRadius
        {
            get
            {
                return _mousePointerCrosshairsRadius;
            }

            set
            {
                if (value != _mousePointerCrosshairsRadius)
                {
                    _mousePointerCrosshairsRadius = value;
                    MousePointerCrosshairsSettingsConfig.Properties.CrosshairsRadius.Value = value;
                    NotifyMousePointerCrosshairsPropertyChanged();
                }
            }
        }

        public int MousePointerCrosshairsThickness
        {
            get
            {
                return _mousePointerCrosshairsThickness;
            }

            set
            {
                if (value != _mousePointerCrosshairsThickness)
                {
                    _mousePointerCrosshairsThickness = value;
                    MousePointerCrosshairsSettingsConfig.Properties.CrosshairsThickness.Value = value;
                    NotifyMousePointerCrosshairsPropertyChanged();
                }
            }
        }

        public string MousePointerCrosshairsBorderColor
        {
            get
            {
                return _mousePointerCrosshairsBorderColor;
            }

            set
            {
                value = SettingsUtilities.ToRGBHex(value);
                if (!value.Equals(_mousePointerCrosshairsBorderColor, StringComparison.OrdinalIgnoreCase))
                {
                    _mousePointerCrosshairsBorderColor = value;
                    MousePointerCrosshairsSettingsConfig.Properties.CrosshairsBorderColor.Value = value;
                    NotifyMousePointerCrosshairsPropertyChanged();
                }
            }
        }

        public int MousePointerCrosshairsBorderSize
        {
            get
            {
                return _mousePointerCrosshairsBorderSize;
            }

            set
            {
                if (value != _mousePointerCrosshairsBorderSize)
                {
                    _mousePointerCrosshairsBorderSize = value;
                    MousePointerCrosshairsSettingsConfig.Properties.CrosshairsBorderSize.Value = value;
                    NotifyMousePointerCrosshairsPropertyChanged();
                }
            }
        }

        public bool MousePointerCrosshairsAutoHide
        {
            get
            {
                return _mousePointerCrosshairsAutoHide;
            }

            set
            {
                if (value != _mousePointerCrosshairsAutoHide)
                {
                    _mousePointerCrosshairsAutoHide = value;
                    MousePointerCrosshairsSettingsConfig.Properties.CrosshairsAutoHide.Value = value;
                    NotifyMousePointerCrosshairsPropertyChanged();
                }
            }
        }

        public bool MousePointerCrosshairsIsFixedLengthEnabled
        {
            get
            {
                return _mousePointerCrosshairsIsFixedLengthEnabled;
            }

            set
            {
                if (value != _mousePointerCrosshairsIsFixedLengthEnabled)
                {
                    _mousePointerCrosshairsIsFixedLengthEnabled = value;
                    MousePointerCrosshairsSettingsConfig.Properties.CrosshairsIsFixedLengthEnabled.Value = value;
                    NotifyMousePointerCrosshairsPropertyChanged();
                }
            }
        }

        public int MousePointerCrosshairsFixedLength
        {
            get
            {
                return _mousePointerCrosshairsFixedLength;
            }

            set
            {
                if (value != _mousePointerCrosshairsFixedLength)
                {
                    _mousePointerCrosshairsFixedLength = value;
                    MousePointerCrosshairsSettingsConfig.Properties.CrosshairsFixedLength.Value = value;
                    NotifyMousePointerCrosshairsPropertyChanged();
                }
            }
        }

        public bool MousePointerCrosshairsAutoActivate
        {
            get
            {
                return _mousePointerCrosshairsAutoActivate;
            }

            set
            {
                if (value != _mousePointerCrosshairsAutoActivate)
                {
                    _mousePointerCrosshairsAutoActivate = value;
                    MousePointerCrosshairsSettingsConfig.Properties.AutoActivate.Value = value;
                    NotifyMousePointerCrosshairsPropertyChanged();
                }
            }
        }

        public void NotifyMousePointerCrosshairsPropertyChanged([CallerMemberName] string propertyName = null)
        {
            OnPropertyChanged(propertyName);

            SndMousePointerCrosshairsSettings outsettings = new SndMousePointerCrosshairsSettings(MousePointerCrosshairsSettingsConfig);
            SndModuleSettings<SndMousePointerCrosshairsSettings> ipcMessage = new SndModuleSettings<SndMousePointerCrosshairsSettings>(outsettings);
            SendConfigMSG(ipcMessage.ToJsonString());
            SettingsUtils.SaveSettings(MousePointerCrosshairsSettingsConfig.ToJsonString(), MousePointerCrosshairsSettings.ModuleName);
        }

        public void RefreshEnabledState()
        {
            InitializeEnabledValues();
            OnPropertyChanged(nameof(IsFindMyMouseEnabled));
            OnPropertyChanged(nameof(IsMouseHighlighterEnabled));
            OnPropertyChanged(nameof(IsMouseJumpEnabled));
            OnPropertyChanged(nameof(IsMousePointerCrosshairsEnabled));
        }

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

        private GpoRuleConfigured _findMyMouseEnabledGpoRuleConfiguration;
        private bool _findMyMouseEnabledStateIsGPOConfigured;
        private bool _isFindMyMouseEnabled;
        private int _findMyMouseActivationMethod;
        private bool _findMyMouseDoNotActivateOnGameMode;
        private string _findMyMouseBackgroundColor;
        private string _findMyMouseSpotlightColor;
        private int _findMyMouseOverlayOpacity;
        private int _findMyMouseSpotlightRadius;
        private int _findMyMouseAnimationDurationMs;
        private int _findMyMouseSpotlightInitialZoom;
        private string _findMyMouseExcludedApps;
        private int _findMyMouseShakingMinimumDistance;
        private int _findMyMouseShakingIntervalMs;
        private int _findMyMouseShakingFactor;

        private GpoRuleConfigured _highlighterEnabledGpoRuleConfiguration;
        private bool _highlighterEnabledStateIsGPOConfigured;
        private bool _isMouseHighlighterEnabled;
        private string _highlighterLeftButtonClickColor;
        private string _highlighterRightButtonClickColor;
        private string _highlighterAlwaysColor;
        private int _highlighterRadius;
        private int _highlightFadeDelayMs;
        private int _highlightFadeDurationMs;
        private bool _highlighterAutoActivate;

        private GpoRuleConfigured _jumpEnabledGpoRuleConfiguration;
        private bool _jumpEnabledStateIsGPOConfigured;
        private bool _isMouseJumpEnabled;

        private GpoRuleConfigured _mousePointerCrosshairsEnabledGpoRuleConfiguration;
        private bool _mousePointerCrosshairsEnabledStateIsGPOConfigured;
        private bool _isMousePointerCrosshairsEnabled;
        private string _mousePointerCrosshairsColor;
        private int _mousePointerCrosshairsOpacity;
        private int _mousePointerCrosshairsRadius;
        private int _mousePointerCrosshairsThickness;
        private string _mousePointerCrosshairsBorderColor;
        private int _mousePointerCrosshairsBorderSize;
        private bool _mousePointerCrosshairsAutoHide;
        private bool _mousePointerCrosshairsIsFixedLengthEnabled;
        private int _mousePointerCrosshairsFixedLength;
        private bool _mousePointerCrosshairsAutoActivate;
        private bool _isAnimationEnabledBySystem;
    }
}
