package com.terry.engine {
	import flash.display.DisplayObject;
	import flash.events.KeyboardEvent;
	
	public class key
	{
		public static var ESCAPE:Boolean;
		public static var F1:Boolean;
		public static var F2:Boolean;
		public static var F3:Boolean;
		public static var F4:Boolean;
		public static var F5:Boolean;
		public static var F6:Boolean;
		public static var F7:Boolean;
		public static var F8:Boolean;
		public static var F9:Boolean;
		public static var F10:Boolean;
		public static var F11:Boolean;
		public static var F12:Boolean;
		public static var ONE:Boolean;
		public static var TWO:Boolean;
		public static var THREE:Boolean;
		public static var FOUR:Boolean;
		public static var FIVE:Boolean;
		public static var SIX:Boolean;
		public static var SEVEN:Boolean;
		public static var EIGHT:Boolean;
		public static var NINE:Boolean;
		public static var ZERO:Boolean;
		public static var MINUS:Boolean;
		public static var PLUS:Boolean;
		public static var DELETE:Boolean;
		public static var BACKSPACE:Boolean;
		public static var Q:Boolean;
		public static var W:Boolean;
		public static var E:Boolean;
		public static var R:Boolean;
		public static var T:Boolean;
		public static var Y:Boolean;
		public static var U:Boolean;
		public static var I:Boolean;
		public static var O:Boolean;
		public static var P:Boolean;
		public static var LBRACKET:Boolean;
		public static var RBRACKET:Boolean;
		public static var BACKSLASH:Boolean;
		public static var CAPSLOCK:Boolean;
		public static var A:Boolean;
		public static var S:Boolean;
		public static var D:Boolean;
		public static var F:Boolean;
		public static var G:Boolean;
		public static var H:Boolean;
		public static var J:Boolean;
		public static var K:Boolean;
		public static var L:Boolean;
		public static var SEMICOLON:Boolean;
		public static var QUOTE:Boolean;
		public static var ENTER:Boolean;
		public static var SHIFT:Boolean;
		public static var Z:Boolean;
		public static var X:Boolean;
		public static var C:Boolean;
		public static var V:Boolean;
		public static var B:Boolean;
		public static var N:Boolean;
		public static var M:Boolean;
		public static var COMMA:Boolean;
		public static var PERIOD:Boolean;
		public static var SLASH:Boolean;
		public static var CONTROL:Boolean;
		public static var ALT:Boolean;
		public static var SPACE:Boolean;
		public static var UP:Boolean;
		public static var DOWN:Boolean;
		public static var LEFT:Boolean;
		public static var RIGHT:Boolean;
		
		private static var arr:Object;
		
		/**
		 * @private
		 */
		protected static var _lookup:Object;
		/**
		 * @private
		 */
		protected static var _map:Array;
		/**
		 * @private
		 */
		protected static const _t:uint = 256;
		
		/**
		 * Constructor
		 */
		public static function init(stage:DisplayObject):void
		{
			stage.addEventListener(KeyboardEvent.KEY_DOWN, handleKeyDown);
			stage.addEventListener(KeyboardEvent.KEY_UP, handleKeyUp);
			
			
			arr = new Object();
			
			//BASIC STORAGE & TRACKING			
			var i:uint = 0;
			_lookup = new Object();
			_map = new Array(_t);
			keyheld = new Array(_t);
			
			//LETTERS
			for(i = 65; i <= 90; i++)
				addKey(String.fromCharCode(i),i);
			
			//NUMBERS
			i = 48;
			addKey("ZERO",i++);
			addKey("ONE",i++);
			addKey("TWO",i++);
			addKey("THREE",i++);
			addKey("FOUR",i++);
			addKey("FIVE",i++);
			addKey("SIX",i++);
			addKey("SEVEN",i++);
			addKey("EIGHT",i++);
			addKey("NINE",i++);
			
			//FUNCTION KEYS
			for(i = 1; i <= 12; i++)
				addKey("F"+i,111+i);
			
			//SPECIAL KEYS + PUNCTUATION
			addKey("ESCAPE",27);
			addKey("MINUS",189);
			addKey("PLUS",187);
			addKey("DELETE",46);
			addKey("BACKSPACE",8);
			addKey("LBRACKET",219);
			addKey("RBRACKET",221);
			addKey("BACKSLASH",220);
			addKey("CAPSLOCK",20);
			addKey("SEMICOLON",186);
			addKey("QUOTE",222);
			addKey("ENTER",13);
			addKey("SHIFT",16);
			addKey("COMMA",188);
			addKey("PERIOD",190);
			addKey("SLASH",191);
			addKey("CONTROL",17);
			addKey("ALT",18);
			addKey("SPACE",32);
			addKey("UP",38);
			addKey("DOWN",40);
			addKey("LEFT",37);
			addKey("RIGHT",39);
		}
		
		/**
		 * Updates the key states (for tracking just pressed, just released, etc).
		 */
		public static function update():void
		{
			for(var i:uint = 0; i < _t; i++)
			{
				if(_map[i] == null) continue;
				var o:Object = _map[i];
				if((o.last == -1) && (o.current == -1)) o.current = 0;
				else if((o.last == 2) && (o.current == 2)) o.current = 1;
				o.last = o.current;
			}
		}
		
		/**
		 * Resets all the keys.
		 */
		public static function reset():void
		{
			for(var i:uint = 0; i < _t; i++)
			{
				if(_map[i] == null) continue;
				var o:Object = _map[i];
				arr[o.name] = false;
				o.current = 0;
				o.last = 0;
			}
		}
		
		/**
		 * Check to see if this key is pressed.
		 * 
		 * @param	Key		One of the key constants listed above (e.g. "LEFT" or "A").
		 * 
		 * @return	Whether the key is pressed
		 */
		public static function pressed(Key:String):Boolean { return arr[Key]; }
		
		/**
		 * Check to see if this key was just pressed.
		 * 
		 * @param	Key		One of the key constants listed above (e.g. "LEFT" or "A").
		 * 
		 * @return	Whether the key was just pressed
		 */
		public static function justPressed(Key:String):Boolean { return _map[_lookup[Key]].current == 2; }
		
		/**
		 * Check to see if this key is just released.
		 * 
		 * @param	Key		One of the key constants listed above (e.g. "LEFT" or "A").
		 * 
		 * @return	Whether the key is just released.
		 */
		public static function justReleased(Key:String):Boolean { return _map[_lookup[Key]].current == -1; }
		
		/**
		 * Event handler so FlxGame can toggle keys.
		 * 
		 * @param	event	A <code>KeyboardEvent</code> object.
		 */
		public static function handleKeyDown(event:KeyboardEvent):void
		{
			var o:Object = _map[event.keyCode];
			if(o == null) return;
			if(o.current > 0) o.current = 1;
			else o.current = 2;
			arr[o.name] = true;
		}
		
		/**
		 * Event handler so FlxGame can toggle keys.
		 * 
		 * @param	event	A <code>KeyboardEvent</code> object.
		 */
		public static function handleKeyUp(event:KeyboardEvent):void
		{
			var o:Object = _map[event.keyCode];
			if(o == null) return;
			if(o.current > 0) o.current = -1;
			else o.current = 0;
			arr[o.name] = false;
		}
		
		public static var keyheld:Array;
		
		/**
		 * An internal helper function used to build the key array.
		 * 
		 * @param	KeyName		String name of the key (e.g. "LEFT" or "A")
		 * @param	KeyCode		The numeric Flash code for this key.
		 */
		protected static function addKey(KeyName:String,KeyCode:uint):void
		{
			_lookup[KeyName] = KeyCode;
			_map[KeyCode] = { name: KeyName, current: 0, last: 0 };
			keyheld[KeyCode] = false;
		}
	}
}
