using System; using System.Collections.Generic; using System.Linq; using Artemis.Core.Modules; using Artemis.Storage.Entities.Profile; namespace Artemis.Core; /// /// Represents the configuration of a profile, contained in a /// public class ProfileConfiguration : BreakableModel, IStorageModel, IDisposable { /// /// Represents an empty profile. /// public static readonly ProfileConfiguration Empty = new(ProfileCategory.Empty, "Empty", "Empty"); private ActivationBehaviour _activationBehaviour; private bool _activationConditionMet; private ProfileCategory _category; private Hotkey? _disableHotkey; private bool _disposed; private Hotkey? _enableHotkey; private ProfileConfigurationHotkeyMode _hotkeyMode; private bool _isBeingEdited; private bool _isMissingModule; private bool _isSuspended; private bool _fadeInAndOut; private Module? _module; private string _name; private int _order; private Profile? _profile; internal ProfileConfiguration(ProfileCategory category, string name, string icon) { _name = name; _category = category; Entity = new ProfileConfigurationEntity(); Icon = new ProfileConfigurationIcon(Entity); Icon.SetIconByName(icon); ActivationCondition = new NodeScript("Activate profile", "Whether or not the profile should be active", this); } internal ProfileConfiguration(ProfileCategory category, ProfileConfigurationEntity entity) { // Will be loaded from the entity _name = null!; _category = category; Entity = entity; Icon = new ProfileConfigurationIcon(Entity); ActivationCondition = new NodeScript("Activate profile", "Whether or not the profile should be active", this); Load(); } /// /// Gets or sets the name of this profile configuration /// public string Name { get => _name; set => SetAndNotify(ref _name, value); } /// /// The order in which this profile appears in the update loop and sidebar /// public int Order { get => _order; set => SetAndNotify(ref _order, value); } /// /// Gets or sets a boolean indicating whether this profile is suspended, disabling it regardless of the /// /// public bool IsSuspended { get => _isSuspended; set => SetAndNotify(ref _isSuspended, value); } /// /// Gets a boolean indicating whether this profile configuration is missing any modules /// public bool IsMissingModule { get => _isMissingModule; private set => SetAndNotify(ref _isMissingModule, value); } /// /// Gets or sets the category of this profile configuration /// public ProfileCategory Category { get => _category; internal set => SetAndNotify(ref _category, value); } /// /// Gets or sets the used to determine hotkey behaviour /// public ProfileConfigurationHotkeyMode HotkeyMode { get => _hotkeyMode; set => SetAndNotify(ref _hotkeyMode, value); } /// /// Gets or sets the hotkey used to enable or toggle the profile /// public Hotkey? EnableHotkey { get => _enableHotkey; set => SetAndNotify(ref _enableHotkey, value); } /// /// Gets or sets the hotkey used to disable the profile /// public Hotkey? DisableHotkey { get => _disableHotkey; set => SetAndNotify(ref _disableHotkey, value); } /// /// Gets or sets the behaviour of when this profile is activated /// public ActivationBehaviour ActivationBehaviour { get => _activationBehaviour; set => SetAndNotify(ref _activationBehaviour, value); } /// /// Gets a boolean indicating whether the activation conditions where met during the last call /// public bool ActivationConditionMet { get => _activationConditionMet; private set => SetAndNotify(ref _activationConditionMet, value); } /// /// Gets or sets a boolean indicating whether this profile configuration is being edited /// public bool IsBeingEdited { get => _isBeingEdited; set => SetAndNotify(ref _isBeingEdited, value); } /// /// Gets the profile of this profile configuration /// public Profile? Profile { get => _profile; internal set => SetAndNotify(ref _profile, value); } /// /// Gets or sets a boolean indicating whether this profile should fade in and out when enabling or disabling /// public bool FadeInAndOut { get => _fadeInAndOut; set => SetAndNotify(ref _fadeInAndOut, value); } /// /// Gets or sets the module this profile uses /// public Module? Module { get => _module; set { SetAndNotify(ref _module, value); IsMissingModule = false; } } /// /// Gets the icon configuration /// public ProfileConfigurationIcon Icon { get; } /// /// Gets the data model condition that must evaluate to for this profile to be activated /// alongside any activation requirements of the , if set /// public NodeScript ActivationCondition { get; } /// /// Gets the entity used by this profile config /// public ProfileConfigurationEntity Entity { get; } /// /// Gets the ID of the profile of this profile configuration /// public Guid ProfileId => Entity.ProfileId; #region Overrides of BreakableModel /// public override string BrokenDisplayName => "Profile Configuration"; #endregion /// /// Updates this configurations activation condition status /// public void Update() { if (_disposed) throw new ObjectDisposedException("ProfileConfiguration"); if (!ActivationCondition.ExitNodeConnected) { ActivationConditionMet = true; } else { ActivationCondition.Run(); ActivationConditionMet = ActivationCondition.Result; } } /// /// Determines whether the profile of this configuration should be active /// /// Whether or not to take activation conditions into consideration public bool ShouldBeActive(bool includeActivationCondition) { if (_disposed) throw new ObjectDisposedException("ProfileConfiguration"); if (IsBeingEdited) return true; if (Category.IsSuspended || IsSuspended || IsMissingModule) return false; if (includeActivationCondition) return ActivationConditionMet && (Module == null || Module.IsActivated); return Module == null || Module.IsActivated; } /// public override string ToString() { return $"[ProfileConfiguration] {nameof(Name)}: {Name}"; } internal void LoadModules(List enabledModules) { if (_disposed) throw new ObjectDisposedException("ProfileConfiguration"); Module = enabledModules.FirstOrDefault(m => m.Id == Entity.ModuleId); IsMissingModule = Module == null && Entity.ModuleId != null; } /// public void Dispose() { _disposed = true; ActivationCondition.Dispose(); } #region Implementation of IStorageModel /// public void Load() { if (_disposed) throw new ObjectDisposedException("ProfileConfiguration"); Name = Entity.Name; IsSuspended = Entity.IsSuspended; ActivationBehaviour = (ActivationBehaviour) Entity.ActivationBehaviour; HotkeyMode = (ProfileConfigurationHotkeyMode) Entity.HotkeyMode; FadeInAndOut = Entity.FadeInAndOut; Order = Entity.Order; Icon.Load(); if (Entity.ActivationCondition != null) ActivationCondition.LoadFromEntity(Entity.ActivationCondition); EnableHotkey = Entity.EnableHotkey != null ? new Hotkey(Entity.EnableHotkey) : null; DisableHotkey = Entity.DisableHotkey != null ? new Hotkey(Entity.DisableHotkey) : null; } /// public void Save() { if (_disposed) throw new ObjectDisposedException("ProfileConfiguration"); Entity.Name = Name; Entity.IsSuspended = IsSuspended; Entity.ActivationBehaviour = (int) ActivationBehaviour; Entity.HotkeyMode = (int) HotkeyMode; Entity.ProfileCategoryId = Category.Entity.Id; Entity.FadeInAndOut = FadeInAndOut; Entity.Order = Order; Icon.Save(); ActivationCondition.Save(); Entity.ActivationCondition = ActivationCondition.Entity; EnableHotkey?.Save(); Entity.EnableHotkey = EnableHotkey?.Entity; DisableHotkey?.Save(); Entity.DisableHotkey = DisableHotkey?.Entity; if (!IsMissingModule) Entity.ModuleId = Module?.Id; } #endregion } /// /// Represents a type of behaviour when this profile is activated /// public enum ActivationBehaviour { /// /// Do nothing to other profiles /// None, /// /// Disable all other profiles /// DisableOthers, /// /// Disable all other profiles below this one /// DisableOthersBelow, /// /// Disable all other profiles above this one /// DisableOthersAbove, /// /// Disable all other profiles in the same category /// DisableOthersInCategory, /// /// Disable all other profiles below this one in the same category /// DisableOthersBelowInCategory, /// /// Disable all other profiles above this one in the same category /// DisableOthersAboveInCategory } /// /// Represents a hotkey mode for a profile configuration /// public enum ProfileConfigurationHotkeyMode { /// /// Use no hotkeys /// None, /// /// Toggle the profile with one hotkey /// Toggle, /// /// Enable and disable the profile with two separate hotkeys /// EnableDisable }