using System;
using System.Collections.Generic;
using System.Text;

namespace SharpQuake
{
	internal static class cmd
	{
		public static cmd_source_t Source
		{
			get
			{
				return cmd._Source;
			}
		}

		public static int Argc
		{
			get
			{
				return cmd._Argc;
			}
		}

		public static string Args
		{
			get
			{
				return cmd._Args;
			}
		}

		internal static bool Wait
		{
			get
			{
				return cmd._Wait;
			}
			set
			{
				cmd._Wait = value;
			}
		}

		public static void Init()
		{
			cmd.Add("stuffcmds", new xcommand_t(cmd.StuffCmds_f));
			cmd.Add("exec", new xcommand_t(cmd.Exec_f));
			cmd.Add("echo", new xcommand_t(cmd.Echo_f));
			cmd.Add("alias", new xcommand_t(cmd.Alias_f));
			cmd.Add("cmd", new xcommand_t(cmd.ForwardToServer));
			cmd.Add("wait", new xcommand_t(Cbuf.Cmd_Wait_f));
		}

		public static void Add(string name, xcommand_t function)
		{
			if (host.IsInitialized)
			{
				sys.Error("Cmd.Add after host initialized!", Array.Empty<object>());
			}
			if (cvar.Exists(name))
			{
				Con.Print("Cmd.Add: {0} already defined as a var!\n", new object[]
				{
					name
				});
				return;
			}
			if (cmd.Exists(name))
			{
				Con.Print("Cmd.Add: {0} already defined!\n", new object[]
				{
					name
				});
				return;
			}
			cmd._Functions.Add(name, function);
		}

		public static string[] Complete(string partial)
		{
			if (string.IsNullOrEmpty(partial))
			{
				return null;
			}
			List<string> list = new List<string>();
			foreach (string text in cmd._Functions.Keys)
			{
				if (text.StartsWith(partial))
				{
					list.Add(text);
				}
			}
			if (list.Count <= 0)
			{
				return null;
			}
			return list.ToArray();
		}

		public static string Argv(int arg)
		{
			if (arg < 0 || arg >= cmd._Argc)
			{
				return string.Empty;
			}
			return cmd._Argv[arg];
		}

		public static bool Exists(string name)
		{
			return cmd.Find(name) != null;
		}

		public static void TokenizeString(string text)
		{
			cmd._Argc = 0;
			cmd._Args = null;
			cmd._Argv = null;
			List<string> list = new List<string>(80);
			while (!string.IsNullOrEmpty(text))
			{
				if (cmd._Argc == 1)
				{
					cmd._Args = text;
				}
				text = common.Parse(text);
				if (string.IsNullOrEmpty(common.Token))
				{
					break;
				}
				if (cmd._Argc < 80)
				{
					list.Add(common.Token);
					cmd._Argc++;
				}
			}
			cmd._Argv = list.ToArray();
		}

		public static void ExecuteString(string text, cmd_source_t src)
		{
			cmd._Source = src;
			cmd.TokenizeString(text);
			if (cmd._Argc <= 0)
			{
				return;
			}
			xcommand_t xcommand_t = cmd.Find(cmd._Argv[0]);
			if (xcommand_t != null)
			{
				xcommand_t();
				return;
			}
			string text2 = cmd.FindAlias(cmd._Argv[0]);
			if (!string.IsNullOrEmpty(text2))
			{
				Cbuf.InsertText(text2);
				return;
			}
			if (!cvar.Command())
			{
				Con.Print("Unknown command \"{0}\"\n", new object[]
				{
					cmd._Argv[0]
				});
			}
		}

		public static void ForwardToServer()
		{
			if (client.cls.state != cactive_t.ca_connected)
			{
				Con.Print("Can't \"{0}\", not connected\n", new object[]
				{
					cmd.Argv(0)
				});
				return;
			}
			if (client.cls.demoplayback)
			{
				return;
			}
			MsgWriter message = client.cls.message;
			message.WriteByte(4);
			if (!cmd.Argv(0).Equals("cmd"))
			{
				message.Print(cmd.Argv(0) + " ");
			}
			if (cmd.Argc > 1)
			{
				message.Print(cmd.Args);
				return;
			}
			message.Print("\n");
		}

		public static string JoinArgv()
		{
			return string.Join(" ", cmd._Argv);
		}

		private static xcommand_t Find(string name)
		{
			xcommand_t result;
			cmd._Functions.TryGetValue(name, out result);
			return result;
		}

		private static string FindAlias(string name)
		{
			string result;
			cmd._Aliases.TryGetValue(name, out result);
			return result;
		}

		private static void StuffCmds_f()
		{
			if (cmd._Argc != 1)
			{
				Con.Print("stuffcmds : execute command line parameters\n", Array.Empty<object>());
				return;
			}
			StringBuilder stringBuilder = new StringBuilder(1024);
			for (int i = 1; i < cmd._Argc; i++)
			{
				if (!string.IsNullOrEmpty(cmd._Argv[i]))
				{
					stringBuilder.Append(cmd._Argv[i]);
					if (i + 1 < cmd._Argc)
					{
						stringBuilder.Append(" ");
					}
				}
			}
			string text = stringBuilder.ToString();
			stringBuilder.Length = 0;
			for (int j = 0; j < text.Length; j++)
			{
				if (text[j] == '+')
				{
					j++;
					int num = j;
					while (num < text.Length && text[num] != '+' && text[num] != '-')
					{
						num++;
					}
					stringBuilder.Append(text.Substring(j, num - j + 1));
					stringBuilder.AppendLine();
					j = num - 1;
				}
			}
			if (stringBuilder.Length > 0)
			{
				Cbuf.InsertText(stringBuilder.ToString());
			}
		}

		private static void Exec_f()
		{
			if (cmd._Argc != 2)
			{
				Con.Print("exec <filename> : execute a script file\n", Array.Empty<object>());
				return;
			}
			byte[] array = common.LoadFile(cmd._Argv[1]);
			if (array == null)
			{
				Con.Print("couldn't exec {0}\n", new object[]
				{
					cmd._Argv[1]
				});
				return;
			}
			string @string = Encoding.ASCII.GetString(array);
			Con.Print("execing {0}\n", new object[]
			{
				cmd._Argv[1]
			});
			Cbuf.InsertText(@string);
		}

		private static void Echo_f()
		{
			for (int i = 1; i < cmd._Argc; i++)
			{
				Con.Print("{0} ", new object[]
				{
					cmd._Argv[i]
				});
			}
			Con.Print("\n", Array.Empty<object>());
		}

		private static void Alias_f()
		{
			if (cmd._Argc == 1)
			{
				Con.Print("Current alias commands:\n", Array.Empty<object>());
				foreach (KeyValuePair<string, string> keyValuePair in cmd._Aliases)
				{
					Con.Print("{0} : {1}\n", new object[]
					{
						keyValuePair.Key,
						keyValuePair.Value
					});
				}
				return;
			}
			string text = cmd._Argv[1];
			if (text.Length >= 32)
			{
				Con.Print("Alias name is too long\n", Array.Empty<object>());
				return;
			}
			StringBuilder stringBuilder = new StringBuilder(1024);
			for (int i = 2; i < cmd._Argc; i++)
			{
				stringBuilder.Append(cmd._Argv[i]);
				if (i + 1 < cmd._Argc)
				{
					stringBuilder.Append(" ");
				}
			}
			stringBuilder.AppendLine();
			cmd._Aliases[text] = stringBuilder.ToString();
		}

		private const int MAX_ALIAS_NAME = 32;

		private const int MAX_ARGS = 80;

		private static cmd_source_t _Source;

		private static Dictionary<string, string> _Aliases = new Dictionary<string, string>();

		private static Dictionary<string, xcommand_t> _Functions = new Dictionary<string, xcommand_t>();

		private static int _Argc;

		private static string[] _Argv;

		private static string _Args;

		private static bool _Wait;
	}
}
