using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using Decal.Interop.DHS;

namespace Decal.Adapter.Wrappers;

[CLSCompliant(true)]
public class HotkeySystem : MarshalByRefObject, IDisposable
{
	private Decal.Interop.DHS.HotkeySystem myHKS;

	private bool isDisposed;

	private EventHandler<HotkeyEventArgs> mHotkey;

	[CLSCompliant(false)]
	[EditorBrowsable(EditorBrowsableState.Never)]
	public Decal.Interop.DHS.HotkeySystem Underlying => myHKS;

	public event EventHandler<HotkeyEventArgs> Hotkey
	{
		add
		{
			mHotkey = (EventHandler<HotkeyEventArgs>)Delegate.Combine(mHotkey, value);
		}
		remove
		{
			mHotkey = (EventHandler<HotkeyEventArgs>)Delegate.Remove(mHotkey, value);
		}
	}

	internal HotkeySystem(Decal.Interop.DHS.HotkeySystem hks)
	{
		myHKS = hks;
		myHKS.HotkeyEvent += myHKS_HotkeyEvent;
	}

	~HotkeySystem()
	{
		Dispose(disposing: false);
	}

	public void Dispose()
	{
		Dispose(disposing: true);
		GC.SuppressFinalize(this);
	}

	protected virtual void Dispose(bool disposing)
	{
		if (!isDisposed && disposing && myHKS != null)
		{
			myHKS.HotkeyEvent -= myHKS_HotkeyEvent;
		}
		if (myHKS != null)
		{
			Marshal.ReleaseComObject(myHKS);
		}
		isDisposed = true;
	}

	public void AddHotkey(string szPlugin, HotkeyWrapper hotkey)
	{
		if (hotkey == null)
		{
			throw new ArgumentNullException("hotkey");
		}
		AddHotkey(szPlugin, hotkey.Underlying);
	}

	public void AddHotkey(string szPlugin, string szTitle, string szDescription)
	{
		Hotkey hotkey = new HotkeyClass();
		hotkey.EventTitle = szTitle;
		hotkey.EventDescription = szDescription;
		AddHotkey(szPlugin, hotkey);
		Marshal.ReleaseComObject(hotkey);
	}

	public void AddHotkey(string plugin, string title, string description, int virtualKey, bool altState, bool controlState, bool shiftState)
	{
		Hotkey hotkey = new HotkeyClass();
		hotkey.EventTitle = title;
		hotkey.EventDescription = description;
		hotkey.VirtualKey = virtualKey;
		hotkey.AltState = altState;
		hotkey.ControlState = controlState;
		hotkey.ShiftState = shiftState;
		AddHotkey(plugin, hotkey);
		Marshal.ReleaseComObject(hotkey);
	}

	private void AddHotkey(string szPlugin, Hotkey hotkey)
	{
		if (hotkey == null)
		{
			throw new ArgumentNullException("hotkey");
		}
		myHKS.AddHotkey(szPlugin, hotkey);
	}

	public void DeleteHotkey(string plugin, string hotkeyName)
	{
		myHKS.DeleteHotkey(plugin, hotkeyName);
	}

	public bool Exists(string hotkeyName)
	{
		return myHKS.QueryHotkey(hotkeyName);
	}

	public HotkeyWrapper GetHotkey(string plugin, string hotkeyName)
	{
		Hotkey hotkey = myHKS.QueryHotkeyEx(plugin, hotkeyName);
		HotkeyWrapper result = null;
		if (hotkey != null)
		{
			result = new HotkeyWrapper(hotkey);
		}
		return result;
	}

	private void myHKS_HotkeyEvent(string szTitle, ref bool Eat)
	{
		if (mHotkey != null)
		{
			HotkeyEventArgs e = new HotkeyEventArgs(szTitle, Eat);
			mHotkey(this, e);
			Eat = e.Eat;
		}
	}
}
