//
// SingleHookManager.cs
//
// Copyright (c) František Boháček. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using Microsoft.Extensions.Options;
using NosSmooth.LocalBinding;
using NosSmooth.LocalBinding.Hooks;
using NosSmooth.LocalBinding.Options;
using Remora.Results;
namespace NosSmooth.Extensions.SharedBinding.Hooks;
///
/// A hook manager for a single NosSmooth instance using shared data.
///
public class SingleHookManager : IHookManager
{
private readonly SharedHookManager _sharedHookManager;
private readonly HookManagerOptions _options;
private Dictionary _hooks;
private bool _initialized;
///
/// Initializes a new instance of the class.
///
/// The shared hook manager.
/// The hook options.
public SingleHookManager(SharedHookManager sharedHookManager, IOptions options)
{
_hooks = new Dictionary();
_sharedHookManager = sharedHookManager;
_options = options.Value;
}
///
public Optional PacketSend => GetHook(IHookManager.PacketSendName);
///
public Optional PacketReceive => GetHook(IHookManager.PacketReceiveName);
///
public Optional PlayerWalk => GetHook(IHookManager.CharacterWalkName);
///
public Optional EntityFollow => GetHook(IHookManager.EntityFollowName);
///
public Optional EntityUnfollow => GetHook(IHookManager.EntityUnfollowName);
///
public Optional PetWalk => GetHook(IHookManager.PetWalkName);
///
public Optional EntityFocus => GetHook(IHookManager.EntityFocusName);
///
public Optional Periodic => GetHook(IHookManager.PeriodicName);
///
public IReadOnlyList Hooks => _hooks.Values.ToList();
///
public IResult Initialize(NosBindingManager bindingManager, NosBrowserManager browserManager)
{
_initialized = true;
var (hooks, result) = _sharedHookManager.InitializeInstance(bindingManager, browserManager, _options);
_hooks = hooks;
return result;
}
///
public void Enable(IEnumerable names)
{
foreach (var name in names)
{
var hook = GetHook(name);
hook.TryDo(h => h.Enable());
}
}
///
public void Disable(IEnumerable names)
{
foreach (var name in names)
{
var hook = GetHook(name);
hook.TryDo(h => h.Disable());
}
}
///
public void DisableAll()
{
foreach (var hook in _hooks.Values)
{
hook.Disable();
}
}
///
public void EnableAll()
{
foreach (var hook in _hooks.Values)
{
hook.Enable();
}
}
///
public bool IsHookLoaded()
where THook : INostaleHook
=> IsHookLoaded(typeof(THook));
///
public bool IsHookUsable()
where THook : INostaleHook
=> IsHookUsable(typeof(THook));
///
public bool IsHookLoaded(Type hookType)
=> GetHook(hookType).IsPresent;
///
public bool IsHookUsable(Type hookType)
=> GetHook(hookType).TryGet(out var h) && h.IsUsable;
private Optional GetHook(string name)
where T : INostaleHook
{
if (!_initialized)
{
throw new InvalidOperationException
($"Could not load hook {typeof(T)}. Did you forget to call IHookManager.Initialize?");
}
var hook = _hooks.Values.FirstOrDefault(x => x is T);
if (hook is not T typed)
{
return Optional.Empty;
}
return typed;
}
private Optional GetHook(Type hookType)
{
if (!_initialized)
{
throw new InvalidOperationException
($"Could not load hook {hookType.Name}. Did you forget to call IHookManager.Initialize?");
}
var hook = _hooks.Values.FirstOrDefault(hookType.IsInstanceOfType);
if (hook is null)
{
return Optional.Empty;
}
return new Optional(hook);
}
}