using System;
using System.IO;
using System.Text;

namespace SharpQuake
{
	internal static class Key
	{
		public static keydest_t Destination
		{
			get
			{
				return Key._KeyDest;
			}
			set
			{
				Key._KeyDest = value;
			}
		}

		public static bool TeamMessage
		{
			get
			{
				return Key._TeamMessage;
			}
			set
			{
				Key._TeamMessage = value;
			}
		}

		public static char[][] Lines
		{
			get
			{
				return Key._Lines;
			}
		}

		public static int EditLine
		{
			get
			{
				return Key._EditLine;
			}
		}

		public static string ChatBuffer
		{
			get
			{
				return Key._ChatBuffer.ToString();
			}
		}

		public static int LastPress
		{
			get
			{
				return Key._LastPress;
			}
		}

		public static string[] Bindings
		{
			get
			{
				return Key._Bindings;
			}
		}

		public static void Event(int key, bool down)
		{
			Key._KeyDown[key] = down;
			if (!down)
			{
				Key._Repeats[key] = 0;
			}
			Key._LastPress = key;
			Key.KeyCount++;
			if (Key.KeyCount <= 0)
			{
				return;
			}
			if (down)
			{
				Key._Repeats[key]++;
				if (key != 127 && key != 255 && key != 150 && key != 149 && Key._Repeats[key] > 1)
				{
					return;
				}
				if (key >= 200 && string.IsNullOrEmpty(Key._Bindings[key]))
				{
					Con.Print("{0} is unbound, hit F4 to set.\n", new object[]
					{
						Key.KeynumToString(key)
					});
				}
			}
			if (key == 134)
			{
				Key._ShiftDown = down;
			}
			if (key == 27)
			{
				if (!down)
				{
					return;
				}
				switch (Key._KeyDest)
				{
				case keydest_t.key_game:
				case keydest_t.key_console:
					menu.ToggleMenu_f();
					return;
				case keydest_t.key_message:
					Key.KeyMessage(key);
					return;
				case keydest_t.key_menu:
					menu.KeyDown(key);
					return;
				default:
					sys.Error("Bad key_dest", Array.Empty<object>());
					return;
				}
			}
			else
			{
				if (!down)
				{
					string text = Key._Bindings[key];
					if (!string.IsNullOrEmpty(text) && text.StartsWith("+"))
					{
						Cbuf.AddText(string.Format("-{0} {1}\n", text.Substring(1), key));
					}
					if (Key._KeyShift[key] != key)
					{
						text = Key._Bindings[Key._KeyShift[key]];
						if (!string.IsNullOrEmpty(text) && text.StartsWith("+"))
						{
							Cbuf.AddText(string.Format("-{0} {1}\n", text.Substring(1), key));
						}
					}
					return;
				}
				if (client.cls.demoplayback && down && Key._ConsoleKeys[key] && Key._KeyDest == keydest_t.key_game)
				{
					menu.ToggleMenu_f();
					return;
				}
				if ((Key._KeyDest == keydest_t.key_menu && Key._MenuBound[key]) || (Key._KeyDest == keydest_t.key_console && !Key._ConsoleKeys[key]) || (Key._KeyDest == keydest_t.key_game && (!Con.ForcedUp || !Key._ConsoleKeys[key])))
				{
					string text2 = Key._Bindings[key];
					if (!string.IsNullOrEmpty(text2))
					{
						if (text2.StartsWith("+"))
						{
							Cbuf.AddText(string.Format("{0} {1}\n", text2, key));
							return;
						}
						Cbuf.AddText(text2);
						Cbuf.AddText("\n");
					}
					return;
				}
				if (!down)
				{
					return;
				}
				if (Key._ShiftDown)
				{
					key = Key._KeyShift[key];
				}
				switch (Key._KeyDest)
				{
				case keydest_t.key_game:
				case keydest_t.key_console:
					Key.KeyConsole(key);
					return;
				case keydest_t.key_message:
					Key.KeyMessage(key);
					return;
				case keydest_t.key_menu:
					menu.KeyDown(key);
					return;
				default:
					sys.Error("Bad key_dest", Array.Empty<object>());
					return;
				}
			}
		}

		public static void Init()
		{
			for (int i = 0; i < 32; i++)
			{
				Key._Lines[i] = new char[256];
				Key._Lines[i][0] = ']';
			}
			Key.LinePos = 1;
			for (int j = 32; j < 128; j++)
			{
				Key._ConsoleKeys[j] = true;
			}
			Key._ConsoleKeys[13] = true;
			Key._ConsoleKeys[9] = true;
			Key._ConsoleKeys[130] = true;
			Key._ConsoleKeys[131] = true;
			Key._ConsoleKeys[128] = true;
			Key._ConsoleKeys[129] = true;
			Key._ConsoleKeys[127] = true;
			Key._ConsoleKeys[150] = true;
			Key._ConsoleKeys[149] = true;
			Key._ConsoleKeys[134] = true;
			Key._ConsoleKeys[239] = true;
			Key._ConsoleKeys[240] = true;
			Key._ConsoleKeys[96] = false;
			Key._ConsoleKeys[126] = false;
			for (int k = 0; k < 256; k++)
			{
				Key._KeyShift[k] = k;
			}
			for (int l = 97; l <= 122; l++)
			{
				Key._KeyShift[l] = l - 97 + 65;
			}
			Key._KeyShift[49] = 33;
			Key._KeyShift[50] = 64;
			Key._KeyShift[51] = 35;
			Key._KeyShift[52] = 36;
			Key._KeyShift[53] = 37;
			Key._KeyShift[54] = 94;
			Key._KeyShift[55] = 38;
			Key._KeyShift[56] = 42;
			Key._KeyShift[57] = 40;
			Key._KeyShift[48] = 41;
			Key._KeyShift[45] = 95;
			Key._KeyShift[61] = 43;
			Key._KeyShift[44] = 60;
			Key._KeyShift[46] = 62;
			Key._KeyShift[47] = 63;
			Key._KeyShift[59] = 58;
			Key._KeyShift[39] = 34;
			Key._KeyShift[91] = 123;
			Key._KeyShift[93] = 125;
			Key._KeyShift[96] = 126;
			Key._KeyShift[92] = 124;
			Key._MenuBound[27] = true;
			for (int m = 0; m < 12; m++)
			{
				Key._MenuBound[135 + m] = true;
			}
			cmd.Add("bind", new xcommand_t(Key.Bind_f));
			cmd.Add("unbind", new xcommand_t(Key.Unbind_f));
			cmd.Add("unbindall", new xcommand_t(Key.UnbindAll_f));
		}

		public static void WriteBindings(Stream dest)
		{
			StringBuilder stringBuilder = new StringBuilder(4096);
			for (int i = 0; i < 256; i++)
			{
				if (!string.IsNullOrEmpty(Key._Bindings[i]))
				{
					stringBuilder.Append("bind \"");
					stringBuilder.Append(Key.KeynumToString(i));
					stringBuilder.Append("\" \"");
					stringBuilder.Append(Key._Bindings[i]);
					stringBuilder.AppendLine("\"");
				}
			}
			byte[] bytes = Encoding.ASCII.GetBytes(stringBuilder.ToString());
			dest.Write(bytes, 0, bytes.Length);
		}

		public static void SetBinding(int keynum, string binding)
		{
			if (keynum != -1)
			{
				Key._Bindings[keynum] = binding;
			}
		}

		public static void ClearStates()
		{
			for (int i = 0; i < 256; i++)
			{
				Key._KeyDown[i] = false;
				Key._Repeats[i] = 0;
			}
		}

		public static string KeynumToString(int keynum)
		{
			if (keynum == -1)
			{
				return "<KEY NOT FOUND>";
			}
			if (keynum > 32 && keynum < 127)
			{
				return ((char)keynum).ToString();
			}
			foreach (Key.keyname_t keyname_t in Key._KeyNames)
			{
				if (keyname_t.keynum == keynum)
				{
					return keyname_t.name;
				}
			}
			return "<UNKNOWN KEYNUM>";
		}

		private static int StringToKeynum(string str)
		{
			if (string.IsNullOrEmpty(str))
			{
				return -1;
			}
			if (str.Length == 1)
			{
				return (int)str[0];
			}
			foreach (Key.keyname_t keyname_t in Key._KeyNames)
			{
				if (common.SameText(keyname_t.name, str))
				{
					return keyname_t.keynum;
				}
			}
			return -1;
		}

		private static void Unbind_f()
		{
			if (cmd.Argc != 2)
			{
				Con.Print("unbind <key> : remove commands from a key\n", Array.Empty<object>());
				return;
			}
			int num = Key.StringToKeynum(cmd.Argv(1));
			if (num == -1)
			{
				Con.Print("\"{0}\" isn't a valid key\n", new object[]
				{
					cmd.Argv(1)
				});
				return;
			}
			Key.SetBinding(num, null);
		}

		private static void UnbindAll_f()
		{
			for (int i = 0; i < 256; i++)
			{
				if (!string.IsNullOrEmpty(Key._Bindings[i]))
				{
					Key.SetBinding(i, null);
				}
			}
		}

		private static void Bind_f()
		{
			int argc = cmd.Argc;
			if (argc != 2 && argc != 3)
			{
				Con.Print("bind <key> [command] : attach a command to a key\n", Array.Empty<object>());
				return;
			}
			int num = Key.StringToKeynum(cmd.Argv(1));
			if (num == -1)
			{
				Con.Print("\"{0}\" isn't a valid key\n", new object[]
				{
					cmd.Argv(1)
				});
				return;
			}
			if (argc != 2)
			{
				StringBuilder stringBuilder = new StringBuilder(1024);
				for (int i = 2; i < argc; i++)
				{
					if (i > 2)
					{
						stringBuilder.Append(" ");
					}
					stringBuilder.Append(cmd.Argv(i));
				}
				Key.SetBinding(num, stringBuilder.ToString());
				return;
			}
			if (!string.IsNullOrEmpty(Key._Bindings[num]))
			{
				Con.Print("\"{0}\" = \"{1}\"\n", new object[]
				{
					cmd.Argv(1),
					Key._Bindings[num]
				});
				return;
			}
			Con.Print("\"{0}\" is not bound\n", new object[]
			{
				cmd.Argv(1)
			});
		}

		private static void KeyMessage(int key)
		{
			if (key == 13)
			{
				if (Key._TeamMessage)
				{
					Cbuf.AddText("say_team \"");
				}
				else
				{
					Cbuf.AddText("say \"");
				}
				Cbuf.AddText(Key._ChatBuffer.ToString());
				Cbuf.AddText("\"\n");
				Key.Destination = keydest_t.key_game;
				Key._ChatBuffer.Length = 0;
				return;
			}
			if (key == 27)
			{
				Key.Destination = keydest_t.key_game;
				Key._ChatBuffer.Length = 0;
				return;
			}
			if (key < 32 || key > 127)
			{
				return;
			}
			if (key == 127)
			{
				if (Key._ChatBuffer.Length > 0)
				{
					StringBuilder chatBuffer = Key._ChatBuffer;
					int length = chatBuffer.Length;
					chatBuffer.Length = length - 1;
				}
				return;
			}
			if (Key._ChatBuffer.Length == 31)
			{
				return;
			}
			Key._ChatBuffer.Append((char)key);
		}

		private static void KeyConsole(int key)
		{
			if (key == 13)
			{
				string text = new string(Key._Lines[Key._EditLine]).TrimEnd(new char[]
				{
					'\0',
					' '
				});
				Cbuf.AddText(text.Substring(1));
				Cbuf.AddText("\n");
				Con.Print("{0}\n", new object[]
				{
					text
				});
				Key._EditLine = (Key._EditLine + 1 & 31);
				Key._HistoryLine = Key._EditLine;
				Key._Lines[Key._EditLine][0] = ']';
				Key.LinePos = 1;
				if (client.cls.state == cactive_t.ca_disconnected)
				{
					Scr.UpdateScreen();
				}
				return;
			}
			if (key == 9)
			{
				string partial = new string(Key._Lines[Key._EditLine], 1, 255).TrimEnd(new char[]
				{
					'\0',
					' '
				});
				string[] array = cmd.Complete(partial);
				string[] array2 = cvar.CompleteName(partial);
				string text2 = null;
				if (array != null)
				{
					if (array.Length > 1 || array2 != null)
					{
						Con.Print("\nCommands:\n", Array.Empty<object>());
						foreach (string text3 in array)
						{
							Con.Print("  {0}\n", new object[]
							{
								text3
							});
						}
					}
					else
					{
						text2 = array[0];
					}
				}
				if (array2 != null)
				{
					if (array2.Length > 1 || array != null)
					{
						Con.Print("\nVariables:\n", Array.Empty<object>());
						foreach (string text4 in array2)
						{
							Con.Print("  {0}\n", new object[]
							{
								text4
							});
						}
					}
					else if (text2 == null)
					{
						text2 = array2[0];
					}
				}
				if (!string.IsNullOrEmpty(text2))
				{
					int num = Math.Min(text2.Length, 253);
					for (int j = 0; j < num; j++)
					{
						Key._Lines[Key._EditLine][j + 1] = text2[j];
					}
					Key.LinePos = num + 1;
					Key._Lines[Key._EditLine][Key.LinePos] = ' ';
					Key.LinePos++;
					Key._Lines[Key._EditLine][Key.LinePos] = '\0';
					return;
				}
			}
			if (key == 127 || key == 130)
			{
				if (Key.LinePos > 1)
				{
					Key.LinePos--;
				}
				return;
			}
			if (key == 128)
			{
				do
				{
					Key._HistoryLine = (Key._HistoryLine - 1 & 31);
				}
				while (Key._HistoryLine != Key._EditLine && Key._Lines[Key._HistoryLine][1] == '\0');
				if (Key._HistoryLine == Key._EditLine)
				{
					Key._HistoryLine = (Key._EditLine + 1 & 31);
				}
				Array.Copy(Key._Lines[Key._HistoryLine], Key._Lines[Key._EditLine], 256);
				Key.LinePos = 0;
				while (Key._Lines[Key._EditLine][Key.LinePos] != '\0' && Key.LinePos < 256)
				{
					Key.LinePos++;
				}
				return;
			}
			if (key == 129)
			{
				if (Key._HistoryLine == Key._EditLine)
				{
					return;
				}
				do
				{
					Key._HistoryLine = (Key._HistoryLine + 1 & 31);
				}
				while (Key._HistoryLine != Key._EditLine && Key._Lines[Key._HistoryLine][1] == '\0');
				if (Key._HistoryLine == Key._EditLine)
				{
					Key._Lines[Key._EditLine][0] = ']';
					Key.LinePos = 1;
					return;
				}
				Array.Copy(Key._Lines[Key._HistoryLine], Key._Lines[Key._EditLine], 256);
				Key.LinePos = 0;
				while (Key._Lines[Key._EditLine][Key.LinePos] != '\0' && Key.LinePos < 256)
				{
					Key.LinePos++;
				}
				return;
			}
			else
			{
				if (key == 150 || key == 239)
				{
					Con.BackScroll += 2;
					if (Con.BackScroll > Con.TotalLines - (Scr.vid.height >> 3) - 1)
					{
						Con.BackScroll = Con.TotalLines - (Scr.vid.height >> 3) - 1;
					}
					return;
				}
				if (key == 149 || key == 240)
				{
					Con.BackScroll -= 2;
					if (Con.BackScroll < 0)
					{
						Con.BackScroll = 0;
					}
					return;
				}
				if (key == 151)
				{
					Con.BackScroll = Con.TotalLines - (Scr.vid.height >> 3) - 1;
					return;
				}
				if (key == 152)
				{
					Con.BackScroll = 0;
					return;
				}
				if (key < 32 || key > 127)
				{
					return;
				}
				if (Key.LinePos < 255)
				{
					Key._Lines[Key._EditLine][Key.LinePos] = (char)key;
					Key.LinePos++;
					Key._Lines[Key._EditLine][Key.LinePos] = '\0';
				}
				return;
			}
		}

		public const int K_TAB = 9;

		public const int K_ENTER = 13;

		public const int K_ESCAPE = 27;

		public const int K_SPACE = 32;

		public const int K_BACKSPACE = 127;

		public const int K_UPARROW = 128;

		public const int K_DOWNARROW = 129;

		public const int K_LEFTARROW = 130;

		public const int K_RIGHTARROW = 131;

		public const int K_ALT = 132;

		public const int K_CTRL = 133;

		public const int K_SHIFT = 134;

		public const int K_F1 = 135;

		public const int K_F2 = 136;

		public const int K_F3 = 137;

		public const int K_F4 = 138;

		public const int K_F5 = 139;

		public const int K_F6 = 140;

		public const int K_F7 = 141;

		public const int K_F8 = 142;

		public const int K_F9 = 143;

		public const int K_F10 = 144;

		public const int K_F11 = 145;

		public const int K_F12 = 146;

		public const int K_INS = 147;

		public const int K_DEL = 148;

		public const int K_PGDN = 149;

		public const int K_PGUP = 150;

		public const int K_HOME = 151;

		public const int K_END = 152;

		public const int K_PAUSE = 255;

		public const int K_MOUSE1 = 200;

		public const int K_MOUSE2 = 201;

		public const int K_MOUSE3 = 202;

		public const int K_JOY1 = 203;

		public const int K_JOY2 = 204;

		public const int K_JOY3 = 205;

		public const int K_JOY4 = 206;

		public const int K_AUX1 = 207;

		public const int K_AUX2 = 208;

		public const int K_AUX3 = 209;

		public const int K_AUX4 = 210;

		public const int K_AUX5 = 211;

		public const int K_AUX6 = 212;

		public const int K_AUX7 = 213;

		public const int K_AUX8 = 214;

		public const int K_AUX9 = 215;

		public const int K_AUX10 = 216;

		public const int K_AUX11 = 217;

		public const int K_AUX12 = 218;

		public const int K_AUX13 = 219;

		public const int K_AUX14 = 220;

		public const int K_AUX15 = 221;

		public const int K_AUX16 = 222;

		public const int K_AUX17 = 223;

		public const int K_AUX18 = 224;

		public const int K_AUX19 = 225;

		public const int K_AUX20 = 226;

		public const int K_AUX21 = 227;

		public const int K_AUX22 = 228;

		public const int K_AUX23 = 229;

		public const int K_AUX24 = 230;

		public const int K_AUX25 = 231;

		public const int K_AUX26 = 232;

		public const int K_AUX27 = 233;

		public const int K_AUX28 = 234;

		public const int K_AUX29 = 235;

		public const int K_AUX30 = 236;

		public const int K_AUX31 = 237;

		public const int K_AUX32 = 238;

		public const int K_MWHEELUP = 239;

		public const int K_MWHEELDOWN = 240;

		public static int LinePos;

		public static int KeyCount;

		private const int MAXCMDLINE = 256;

		private static Key.keyname_t[] _KeyNames = new Key.keyname_t[]
		{
			new Key.keyname_t("TAB", 9),
			new Key.keyname_t("ENTER", 13),
			new Key.keyname_t("ESCAPE", 27),
			new Key.keyname_t("SPACE", 32),
			new Key.keyname_t("BACKSPACE", 127),
			new Key.keyname_t("UPARROW", 128),
			new Key.keyname_t("DOWNARROW", 129),
			new Key.keyname_t("LEFTARROW", 130),
			new Key.keyname_t("RIGHTARROW", 131),
			new Key.keyname_t("ALT", 132),
			new Key.keyname_t("CTRL", 133),
			new Key.keyname_t("SHIFT", 134),
			new Key.keyname_t("F1", 135),
			new Key.keyname_t("F2", 136),
			new Key.keyname_t("F3", 137),
			new Key.keyname_t("F4", 138),
			new Key.keyname_t("F5", 139),
			new Key.keyname_t("F6", 140),
			new Key.keyname_t("F7", 141),
			new Key.keyname_t("F8", 142),
			new Key.keyname_t("F9", 143),
			new Key.keyname_t("F10", 144),
			new Key.keyname_t("F11", 145),
			new Key.keyname_t("F12", 146),
			new Key.keyname_t("INS", 147),
			new Key.keyname_t("DEL", 148),
			new Key.keyname_t("PGDN", 149),
			new Key.keyname_t("PGUP", 150),
			new Key.keyname_t("HOME", 151),
			new Key.keyname_t("END", 152),
			new Key.keyname_t("MOUSE1", 200),
			new Key.keyname_t("MOUSE2", 201),
			new Key.keyname_t("MOUSE3", 202),
			new Key.keyname_t("JOY1", 203),
			new Key.keyname_t("JOY2", 204),
			new Key.keyname_t("JOY3", 205),
			new Key.keyname_t("JOY4", 206),
			new Key.keyname_t("AUX1", 207),
			new Key.keyname_t("AUX2", 208),
			new Key.keyname_t("AUX3", 209),
			new Key.keyname_t("AUX4", 210),
			new Key.keyname_t("AUX5", 211),
			new Key.keyname_t("AUX6", 212),
			new Key.keyname_t("AUX7", 213),
			new Key.keyname_t("AUX8", 214),
			new Key.keyname_t("AUX9", 215),
			new Key.keyname_t("AUX10", 216),
			new Key.keyname_t("AUX11", 217),
			new Key.keyname_t("AUX12", 218),
			new Key.keyname_t("AUX13", 219),
			new Key.keyname_t("AUX14", 220),
			new Key.keyname_t("AUX15", 221),
			new Key.keyname_t("AUX16", 222),
			new Key.keyname_t("AUX17", 223),
			new Key.keyname_t("AUX18", 224),
			new Key.keyname_t("AUX19", 225),
			new Key.keyname_t("AUX20", 226),
			new Key.keyname_t("AUX21", 227),
			new Key.keyname_t("AUX22", 228),
			new Key.keyname_t("AUX23", 229),
			new Key.keyname_t("AUX24", 230),
			new Key.keyname_t("AUX25", 231),
			new Key.keyname_t("AUX26", 232),
			new Key.keyname_t("AUX27", 233),
			new Key.keyname_t("AUX28", 234),
			new Key.keyname_t("AUX29", 235),
			new Key.keyname_t("AUX30", 236),
			new Key.keyname_t("AUX31", 237),
			new Key.keyname_t("AUX32", 238),
			new Key.keyname_t("PAUSE", 255),
			new Key.keyname_t("MWHEELUP", 239),
			new Key.keyname_t("MWHEELDOWN", 240),
			new Key.keyname_t("SEMICOLON", 59)
		};

		private static char[][] _Lines = new char[32][];

		private static bool _ShiftDown;

		private static int _LastPress;

		private static int _EditLine;

		private static int _HistoryLine;

		private static keydest_t _KeyDest;

		private static string[] _Bindings = new string[256];

		private static bool[] _ConsoleKeys = new bool[256];

		private static bool[] _MenuBound = new bool[256];

		private static int[] _KeyShift = new int[256];

		private static int[] _Repeats = new int[256];

		private static bool[] _KeyDown = new bool[256];

		private static StringBuilder _ChatBuffer = new StringBuilder(32);

		private static bool _TeamMessage;

		private struct keyname_t
		{
			public keyname_t(string name, int keynum)
			{
				this.name = name;
				this.keynum = keynum;
			}

			public string name;

			public int keynum;
		}
	}
}
