using System;
using System.ComponentModel;
using System.Drawing;
using System.Reflection;
using System.Runtime.InteropServices;
using Decal.Interop.Core;

namespace Decal.Adapter.Wrappers;

[CLSCompliant(true)]
public sealed class HooksWrapper : MarshalByRefObject, IIndexedValueProvider, IDisposable
{
	private IACHooks myHooks;

	private bool isDisposed;

	[CLSCompliant(false)]
	[EditorBrowsable(EditorBrowsableState.Never)]
	public IACHooks Underlying => myHooks;

	public int BusyState => myHooks.BusyState;

	public int BusyStateId => myHooks.BusyStateID;

	public bool ChatState => myHooks.ChatState;

	public CombatState CombatMode => (CombatState)myHooks.CombatMode;

	public int CommandInterpreter => myHooks.CommandInterpreter;

	public int CurrentSelection
	{
		get
		{
			return myHooks.CurrentSelection;
		}
		set
		{
			myHooks.CurrentSelection = value;
		}
	}

	public double Heading
	{
		get
		{
			return myHooks.HeadingDegrees;
		}
		set
		{
			FaceHeading(value, bUnknown: true);
		}
	}

	public double HeadingRadians
	{
		get
		{
			return myHooks.HeadingRadians;
		}
		set
		{
			RadianFaceHeading(value, bUnknown: true);
		}
	}

	public int Landcell => myHooks.Landcell;

	public double LocationX => myHooks.LocationX;

	public double LocationY => myHooks.LocationY;

	public double LocationZ => myHooks.LocationZ;

	public int MaxSelectedStackCount => myHooks.MaxSelectedStackCount;

	public int OpenedContainer => myHooks.OpenedContainer;

	public int PointerState => myHooks.PointerState;

	public int PreviousSelection
	{
		get
		{
			return myHooks.PreviousSelection;
		}
		set
		{
			myHooks.PreviousSelection = value;
		}
	}

	public Rectangle Region3D
	{
		get
		{
			tagRECT aC3DRegionRect = myHooks.AC3DRegionRect;
			return new Rectangle(aC3DRegionRect.left, aC3DRegionRect.top, aC3DRegionRect.right, aC3DRegionRect.bottom);
		}
	}

	public Rectangle RegionWindow
	{
		get
		{
			tagRECT aCWindowRect = myHooks.ACWindowRect;
			return new Rectangle(aCWindowRect.left, aCWindowRect.top, aCWindowRect.right, aCWindowRect.bottom);
		}
	}

	public int SelectedStackCount
	{
		get
		{
			return myHooks.SelectedStackCount;
		}
		set
		{
			myHooks.SelectedStackCount = value;
		}
	}

	public int VendorId => myHooks.VendorID;

	[CLSCompliant(false)]
	public HookIndexer<AttributeType> Attribute => new HookIndexer<AttributeType>(this, hookIndexType.Attribute);

	[CLSCompliant(false)]
	public HookIndexer<AttributeType> AttributeClicks => new HookIndexer<AttributeType>(this, hookIndexType.AttributeClicks);

	[CLSCompliant(false)]
	public HookIndexer<AttributeType> AttributeStart => new HookIndexer<AttributeType>(this, hookIndexType.AttributeStart);

	[CLSCompliant(false)]
	public HookIndexer<AttributeType> AttributeTotalXP => new HookIndexer<AttributeType>(this, hookIndexType.AttributeTotalXP);

	[CLSCompliant(false)]
	public HookIndexer<int> Misc => new HookIndexer<int>(this, hookIndexType.Misc);

	[CLSCompliant(false)]
	public HookIndexer<SkillType> Skill => new HookIndexer<SkillType>(this, hookIndexType.Skill);

	[CLSCompliant(false)]
	public HookIndexer<SkillType> SkillClicks => new HookIndexer<SkillType>(this, hookIndexType.SkillClicks);

	[CLSCompliant(false)]
	public HookIndexer<SkillType> SkillFreePoints => new HookIndexer<SkillType>(this, hookIndexType.SkillFreePoints);

	[CLSCompliant(false)]
	public HookIndexer<SkillType> SkillTotalXP => new HookIndexer<SkillType>(this, hookIndexType.SkillTotalXP);

	[CLSCompliant(false)]
	public HookIndexer<SkillType> SkillTrainLevel => new HookIndexer<SkillType>(this, hookIndexType.SkillTrainLevel);

	[CLSCompliant(false)]
	public HookIndexer<VitalType> Vital => new HookIndexer<VitalType>(this, hookIndexType.Vital);

	[CLSCompliant(false)]
	public HookIndexer<VitalType> VitalClicks => new HookIndexer<VitalType>(this, hookIndexType.VitalClicks);

	[CLSCompliant(false)]
	public HookIndexer<VitalType> VitalTotalXP => new HookIndexer<VitalType>(this, hookIndexType.VitalTotalXP);

	internal HooksWrapper(ACHooks hooks)
	{
		myHooks = hooks;
	}

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

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

	private void Dispose(bool disposing)
	{
		if (!isDisposed)
		{
		}
		if (myHooks != null)
		{
			Marshal.ReleaseComObject(myHooks);
			myHooks = null;
		}
		isDisposed = true;
	}

	public void AddChatText(string text, int color)
	{
		AddChatText(text, color, 0);
	}

	public void AddChatText(string text, int color, int target)
	{
		myHooks.AddChatText(text, color, target);
	}

	public void AddChatTextRaw(string text, int color)
	{
		AddChatTextRaw(text, color, 0);
	}

	public void AddChatTextRaw(string text, int color, int target)
	{
		myHooks.AddChatTextRaw(text, color, target);
	}

	public void AddStatusText(string text)
	{
		myHooks.AddStatusText(text);
	}

	public void ApplyItem(int useThis, int onThis)
	{
		myHooks.ApplyItem(useThis, onThis);
	}

	public void AutoWield(int item)
	{
		myHooks.AutoWield(item);
	}

	public void AutoWield(int item, int slot, int explic, int notexplic)
	{
		myHooks.AutoWieldEx(item, slot, explic, notexplic);
	}

	public void AutoWield(int item, int slot, int explic, int notexplic, int zero1, int zero2)
	{
		myHooks.AutoWieldRaw(item, slot, explic, notexplic, zero1, zero2);
	}

	public void CastSpell(int spellId, int objectId)
	{
		myHooks.CastSpell(spellId, objectId);
	}

	public void DropItem(int objectId)
	{
		myHooks.DropItem(objectId);
	}

	public bool FaceHeading(double heading, bool bUnknown)
	{
		return myHooks.FaceHeading((float)heading, bUnknown);
	}

	public bool RadianFaceHeading(double heading, bool bUnknown)
	{
		if (heading < 0.0)
		{
			throw new ArgumentOutOfRangeException("heading");
		}
		if (heading > Math.PI * 10.0)
		{
			throw new ArgumentOutOfRangeException("heading");
		}
		double num = heading * 180.0 / Math.PI;
		return myHooks.FaceHeading((float)num, bUnknown);
	}

	public void FellowshipRecruit(int lObjectID)
	{
		myHooks.FellowshipRecruit(lObjectID);
	}

	public void FellowshipGrantLeader(int lObjectID)
	{
		myHooks.FellowshipGrantLeader(lObjectID);
	}

	public void FellowshipSetOpen(bool IsOpen)
	{
		myHooks.FellowshipSetOpen(IsOpen);
	}

	public void FellowshipQuit()
	{
		myHooks.FellowshipQuit();
	}

	public void FellowshipDisband()
	{
		myHooks.FellowshipDisband();
	}

	public void FellowshipDismiss(int lObjectID)
	{
		myHooks.FellowshipDismiss(lObjectID);
	}

	public void GiveItem(int lObject, int lDestination)
	{
		myHooks.GiveItem(lObject, lDestination);
	}

	public void RequestId(int objectId)
	{
		CoreManager.Current.IDQueue.AddToQueueForCaller(objectId, Assembly.GetCallingAssembly(), DateTime.MaxValue);
	}

	public void InvokeChatParser(string text)
	{
		myHooks.InvokeChatParser(text);
	}

	public bool IsValidObject(int objectId)
	{
		return myHooks.IsValidObject(objectId);
	}

	public void Logout()
	{
		myHooks.Logout();
	}

	public void MoveItem(int objectId, int packId, int slot, bool stack)
	{
		myHooks.MoveItem(objectId, packId, slot, stack);
	}

	public void MoveItem(int objectId, int destinationId)
	{
		myHooks.MoveItemEx(objectId, destinationId);
	}

	public void MoveItem(int objectId, int destinationId, int moveFlags)
	{
		myHooks.MoveItemExRaw(objectId, destinationId, moveFlags);
	}

	public void SalvagePanelAdd(int objectId)
	{
		myHooks.SalvagePanelAdd(objectId);
	}

	public void SalvagePanelSalvage()
	{
		myHooks.SalvagePanelSalvage();
	}

	public void SelectItem(int objectId)
	{
		myHooks.SelectItem(objectId);
	}

	public void SetAutorun(bool on)
	{
		myHooks.SetAutorun(on);
	}

	public void SetCombatMode(CombatState newMode)
	{
		myHooks.SetCombatMode((int)newMode);
	}

	public void SetCursorPosition(int x, int y)
	{
		myHooks.SetCursorPosition(x, y);
	}

	public void SetIdleTime(double timeout)
	{
		myHooks.SetIdleTime(timeout);
	}

	public void SpellTabAdd(int tab, int index, int spellId)
	{
		myHooks.SpellTabAdd(tab, index, spellId);
	}

	public void SpellTabDelete(int tab, int spellId)
	{
		myHooks.SpellTabDelete(tab, spellId);
	}

	public void TradeAccept()
	{
		myHooks.TradeAccept();
	}

	public void TradeAdd(int objectId)
	{
		myHooks.TradeAdd(objectId);
	}

	public IntPtr PhysicsObject(int objectId)
	{
		return new IntPtr(myHooks.GetPhysicsObjectPtr(objectId));
	}

	public IntPtr WeenieObject(int objectId)
	{
		return new IntPtr(myHooks.GetWeenieObjectPtr(objectId));
	}

	public void TradeDecline()
	{
		myHooks.TradeDecline();
	}

	public void TradeReset()
	{
		myHooks.TradeReset();
	}

	public void TradeEnd()
	{
		myHooks.TradeEnd();
	}

	public IntPtr UIElementLookup(UIElementType pUIElementType)
	{
		return new IntPtr(myHooks.UIElementLookup((int)pUIElementType));
	}

	public void UIElementMove(UIElementType pUIElementType, int x, int y)
	{
		myHooks.UIElementMove((int)pUIElementType, x, y);
	}

	public void UIElementResize(UIElementType pUIElementType, int width, int height)
	{
		myHooks.UIElementResize((int)pUIElementType, width, height);
	}

	public Rectangle UIElementRegion(UIElementType pUIElementType)
	{
		tagRECT tagRECT = myHooks.UIElementRegionRect((int)pUIElementType);
		return new Rectangle(tagRECT.left, tagRECT.top, 1 + tagRECT.right - tagRECT.left, 1 + tagRECT.bottom - tagRECT.top);
	}

	public void UseItem(int objectId, int useState)
	{
		myHooks.UseItem(objectId, useState);
	}

	public void UseItem(int objectId, int useState, int useMethod)
	{
		myHooks.UseItemRaw(objectId, useState, useMethod);
	}

	public void VendorBuyAll()
	{
		myHooks.VendorBuyAll();
	}

	public void VendorAddBuyList(int templateId, int count)
	{
		myHooks.VendorBuyListAdd(templateId, count);
	}

	public void VendorClearBuyList()
	{
		myHooks.VendorBuyListClear();
	}

	public void VendorSellAll()
	{
		myHooks.VendorSellAll();
	}

	public void VendorAddSellList(int itemId)
	{
		myHooks.VendorSellListAdd(itemId);
	}

	public void VendorClearSellList()
	{
		myHooks.VendorSellListClear();
	}

	public void AddSkillExperience(SkillType skill, int experience)
	{
		myHooks.AddSkillExp((eSkill)skill, experience);
	}

	public void AddAttributeExperience(AttributeType attrib, int experience)
	{
		myHooks.AddAttributeExp((eAttribute)attrib, experience);
	}

	public void AddVitalExperience(VitalType vital, int experience)
	{
		myHooks.AddVitalExp((eVital)vital, experience);
	}

	int IIndexedValueProvider.GetIndexedObject(hookIndexType index, int item)
	{
		int result = 0;
		switch (index)
		{
		case hookIndexType.Attribute:
			result = ((dynamic)myHooks).get_Attribute(item);
			break;
		case hookIndexType.AttributeClicks:
			result = ((dynamic)myHooks).get_AttributeClicks((eAttribute)item);
			break;
		case hookIndexType.AttributeStart:
			result = ((dynamic)myHooks).get_AttributeStart((eAttribute)item);
			break;
		case hookIndexType.AttributeTotalXP:
			result = ((dynamic)myHooks).get_AttributeTotalXP((eAttribute)item);
			break;
		case hookIndexType.Skill:
			result = ((dynamic)myHooks).get_Skill(item);
			break;
		case hookIndexType.SkillClicks:
			result = ((dynamic)myHooks).get_SkillClicks((eSkill)item);
			break;
		case hookIndexType.SkillFreePoints:
			result = ((dynamic)myHooks).get_SkillFreePoints((eSkill)item);
			break;
		case hookIndexType.SkillTotalXP:
			result = ((dynamic)myHooks).get_SkillTotalXP((eSkill)item);
			break;
		case hookIndexType.SkillTrainLevel:
			result = (int)((dynamic)myHooks).get_SkillTrainLevel((eSkill)item);
			break;
		case hookIndexType.Vital:
			result = ((dynamic)myHooks).get_Vital(item);
			break;
		case hookIndexType.VitalClicks:
			result = ((dynamic)myHooks).get_VitalClicks((eVital)item);
			break;
		case hookIndexType.VitalTotalXP:
			result = ((dynamic)myHooks).get_VitalTotalXP((eVital)item);
			break;
		case hookIndexType.Misc:
			result = ((dynamic)myHooks).get_Misc(item);
			break;
		}
		return result;
	}
}
