using AllocsFixes.PersistentData;
using System;
using System.Collections.Generic;
using System.Reflection;

namespace AllocsFixes.CustomCommands
{
	public class TeleportPlayer : ConsoleCommand
	{
		private MethodInfo NetConnection_SendPackage = null;

		public TeleportPlayer (ConsoleSdtd cons) : base(cons)
		{
			Type typeClientInfo = Assembly.GetAssembly (typeof(ClientInfo)).GetType ("ClientInfo");
			Type typeNetConnection = typeClientInfo.GetField ("netConnection").FieldType.GetElementType ();
			MethodInfo[] mis = typeNetConnection.GetMethods ();
			foreach (MethodInfo mi in mis) {
				ParameterInfo[] pis = mi.GetParameters ();
				if (pis.Length == 1) {
					if (typeof (Package).Equals (pis[0].ParameterType)) {
						NetConnection_SendPackage = mi;
					}
				}
			}
		}

		public override string Description ()
		{
			return "teleport a player to a given location";
		}

		public override string[] Names ()
		{
			return new string[] { "teleportplayer", "tele" };
		}

		public override void Run (string[] _params)
		{
			try {
				if (_params.Length != 4 && _params.Length != 2) {
					m_Console.SendResult ("Usage: teleportplayer <entityid|playername|steamid> <x> <y> <z>");
					m_Console.SendResult ("   or: teleportplayer <entityid|playername|steamid> <target entityid|playername|steamid>");
				} else {
					Player p1 = PersistentContainer.Instance.Players.GetPlayerByNameOrId (_params [0], true);
					if (p1 == null) {
						m_Console.SendResult ("Playername or entity/steamid id not found.");
						return;
					}
					if (!p1.IsOnline) {
						m_Console.SendResult ("Player not online.");
						return;
					}

					if (_params.Length == 4) {
						int x = int.MinValue;
						int y = int.MinValue;
						int z = int.MinValue;

						int.TryParse (_params [1], out x);
						int.TryParse (_params [2], out y);
						int.TryParse (_params [3], out z);

						if (x == int.MinValue || y == int.MinValue || z == int.MinValue) {
							m_Console.SendResult ("At least one of the given coordinates is not a valid integer");
							return;
						}

						p1.Entity.position.x = x;
						p1.Entity.position.y = y;
						p1.Entity.position.z = z;
					} else {
						Player p2 = PersistentContainer.Instance.Players.GetPlayerByNameOrId (_params [1], true);
						if (p2 == null) {
							m_Console.SendResult ("Target playername or entity/steamid id not found.");
							return;
						}
						if (!p2.IsOnline) {
							m_Console.SendResult ("Target player not online.");
							return;
						}

						p1.Entity.position = p2.Entity.GetPosition();
					}

					NetPackage_EntityPosAndRot pkg = new NetPackage_EntityPosAndRot (p1.Entity);

					if (NetConnection_SendPackage != null) {
						NetConnection_SendPackage.Invoke (p1.ClientInfo.netConnection [0], new object[] {pkg});
					}
				}
			} catch (Exception e) {
				Log.Out ("Error in TeleportPlayer.Run: " + e);
			}
		}

	}
}
