package com.guru.component.virtualKeyboard
{
	import com.guru.call.FunctionCall;
	import com.guru.call.ICall;
	import com.guru.display.button.LabelButton;
	import com.guru.display.button.LabelCheckButton;
	import com.guru.display.LabelMovieClip;
	import flash.display.MovieClip;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.text.TextField;
	import flash.ui.Keyboard;
	/**
	 * ...
	 * @author Eddy Lee
	 */
	public class VirtualKeyboard
	{
		private static var sInstance:VirtualKeyboard;
		
		public static function init(pTimeline_mc:MovieClip):void
		{
			sInstance = new VirtualKeyboard(pTimeline_mc);
		}
		
		public static function getInstance():VirtualKeyboard
		{
			return sInstance;
		}
		
		private var mTimeline_mc:MovieClip;
		private var mKeyboardContent_mc:MovieClip;
		
		private var mLabelBtn_array:Array;
		
		private var mLabel_array:Array = [	["alphabet_a", "a", "A"],
											["alphabet_b", "b", "B"],
											["alphabet_c", "c", "C"],
											["alphabet_d", "d", "D"],
											["alphabet_e", "e", "E"],
											["alphabet_f", "f", "F"],
											["alphabet_g", "g", "G"],
											["alphabet_h", "h", "H"],
											["alphabet_i", "i", "I"],
											["alphabet_j", "j", "J"],
											["alphabet_k", "k", "K"],
											["alphabet_l", "l", "L"],
											["alphabet_m", "m", "M"],
											["alphabet_n", "n", "N"],
											["alphabet_o", "o", "O"],
											["alphabet_p", "p", "P"],
											["alphabet_q", "q", "Q"],
											["alphabet_r", "r", "R"],
											["alphabet_s", "s", "S"],
											["alphabet_t", "t", "T"],
											["alphabet_u", "u", "U"],
											["alphabet_v", "v", "V"],
											["alphabet_w", "w", "W"],
											["alphabet_x", "x", "X"],
											["alphabet_y", "y", "Y"],
											["alphabet_z", "z", "Z"],
											["digit_1", "1", "!"],
											["digit_2", "2", "@"],
											["digit_3", "3", "#"],
											["digit_4", "4", "$"],
											["digit_5", "5", "%"],
											["digit_6", "6", "^"],
											["digit_7", "7", "&"],
											["digit_8", "8", "*"],
											["digit_9", "9", "("],
											["digit_0", "0", ")"],
											["symbol_grave", "`", "~"],
											["symbol_hyphen", "-", "_"],
											["symbol_equal", "=", "+"],
											["symbol_openBracket", "[", "{"],
											["symbol_closeBracket", "]", "}"],
											["symbol_backSlash", "\\", "|"],
											["symbol_semicolon", ";", ":"],
											["symbol_apostrophe", "'", "\""],
											["symbol_comma", ",", "<"],
											["symbol_dot", ".", ">"],
											["symbol_slash", "/", "?"],
											["symbol_space", " ", " "]];
		
		private var mCapsLock_bol:Boolean;
		private var mShiftKey_bol:Boolean;
		private var mCapsLockBtn:LabelCheckButton;
		private var mLeftShiftBtn:LabelCheckButton;
		private var mRightShiftBtn:LabelCheckButton;
		private var mBackSpaceBtn:LabelButton;
		private var mCurrentString_str:String;
		
		private var mControl:LabelMovieClip;
		private var mCloseBtn:LabelButton;
		private var mEnterBtn:LabelButton;
		private var mHideDoneCall:ICall;
		
		private var mFocusdTextField_txt:TextField;
		private var mFocusdTextFieldPosition_num:Number;
		
		public function VirtualKeyboard(pTimeline_mc:MovieClip)
		{
			Logger.eddy("Virtual Keyboard v1.0");
			mTimeline_mc = pTimeline_mc;
			//this.init();
			
			//this.hide();
			//this.show();
			
			mTimeline_mc.stage.addEventListener(Event.ENTER_FRAME, onEnterFrameHandler);
		}
		
		public function setHideDoneCall(pCall:ICall):void
		{
			mHideDoneCall = pCall;
		}
		
		public function hide(pDoneCall:ICall = null):void
		{
			mControl.playTo("hide", new FunctionCall(this, onHideDone, pDoneCall));
		}
		
		public function show(pDoneCall:ICall = null):void
		{
			mTimeline_mc.visible = true;
			this.init();
			mControl.playTo("show", new FunctionCall(this, onShowDone, pDoneCall));
		}
		
		private function onHideDone(pDoneCall:ICall = null):void
		{
			mCloseBtn.reset();
			mEnterBtn.reset();
			mTimeline_mc.visible = false;
			
			if (mHideDoneCall)
				mHideDoneCall.execute();
			if (pDoneCall)
				pDoneCall.execute();
				
			this.dispose();
		}
		
		private function onShowDone(pDoneCall:ICall = null):void
		{
			if (pDoneCall)
				pDoneCall.execute();
		}
		
		public function dispose():void
		{
			mCapsLock_bol:Boolean;
			mShiftKey_bol:Boolean;
			mCapsLockBtn.dispose();
			mLeftShiftBtn.dispose();
			mRightShiftBtn.dispose();
			mBackSpaceBtn.dispose();
			mCurrentString_str = "";
			mControl.dispose();
			mCloseBtn.dispose();
			mEnterBtn.dispose();
			mHideDoneCall = null;
				
			mFocusdTextField_txt = null;
			
			if (mTimeline_mc.stage)
			{
				trace("Kill focus");
				mTimeline_mc.stage.focus = null;
			}
		}
		
		private function init():void
		{
			mKeyboardContent_mc = mTimeline_mc.content_mc;
			mControl = new LabelMovieClip(mTimeline_mc, "hide");
			mCloseBtn = new LabelButton(mTimeline_mc.closeBtn_mc);
			mEnterBtn = new LabelButton(mKeyboardContent_mc.enterBtn_mc);
			mCloseBtn.setPressCall(new FunctionCall(this, hide));
			mEnterBtn.setPressCall(new FunctionCall(this, onEnterBtnPress));
			
			mLabelBtn_array = new Array();
			var btn_mc:MovieClip;
			var btn:VirtualKeyboardLabelButton;
			var i:Number;
			for (i = 0; i < mLabel_array.length; i++ )
			{
				btn_mc = mKeyboardContent_mc[mLabel_array[i][0] + "Btn_mc"];
				btn = new VirtualKeyboardLabelButton(btn_mc, i, mLabel_array[i][1], mLabel_array[i][2]);
				btn.setPressCall(new FunctionCall(this, onInputBtnPress, btn));
				btn.setPressDoneCall(new FunctionCall(btn, btn.reset));
				mLabelBtn_array[mLabel_array[i][1]] = btn;
				mLabelBtn_array[mLabel_array[i][2]] = btn;
			}
			
			mCapsLockBtn = new LabelCheckButton(mKeyboardContent_mc.capsLockBtn_mc);
			mCapsLockBtn.setOnCall(new FunctionCall(this, onCapsLockBtnOn));
			mCapsLockBtn.setOffCall(new FunctionCall(this, onCapsLockBtnOff));
			mLeftShiftBtn = new LabelCheckButton(mKeyboardContent_mc.leftShiftBtn_mc);
			mRightShiftBtn = new LabelCheckButton(mKeyboardContent_mc.rightShiftBtn_mc);
			mLeftShiftBtn.setOnCall(new FunctionCall(this, onShiftBtnOn));
			mLeftShiftBtn.setOffCall(new FunctionCall(this, onShiftBtnOff));
			mRightShiftBtn.setOnCall(new FunctionCall(this, onShiftBtnOn));
			mRightShiftBtn.setOffCall(new FunctionCall(this, onShiftBtnOff));
			
			
			mBackSpaceBtn = new LabelButton(mKeyboardContent_mc.backSpaceBtn_mc);
			mBackSpaceBtn.setPressCall(new FunctionCall(this, onBackSpaceBtnPress));
			mBackSpaceBtn.setPressDoneCall(new FunctionCall(mBackSpaceBtn, mBackSpaceBtn.reset));
			
			mCapsLock_bol = Keyboard.capsLock;
			mShiftKey_bol = false;
			
			//mTimeline_mc.stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDownHandler);
			//mTimeline_mc.stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUpHandler);
		}
		
		private function onEnterBtnPress():void
		{
			this.hide();
		}
		
		private function onEnterFrameHandler(e:Event):void
		{
			if (mTimeline_mc.stage.focus is TextField)
			{
				if (TextField(mTimeline_mc.stage.focus) != mFocusdTextField_txt)
				{
					mFocusdTextField_txt = TextField(mTimeline_mc.stage.focus);
					mCurrentString_str = mFocusdTextField_txt.text;
					
					mFocusdTextFieldPosition_num = mFocusdTextField_txt.caretIndex;
					
					trace("mFocusdTextFieldPosition_num: " + mFocusdTextFieldPosition_num);
					trace("mCurrentString_str: " + mCurrentString_str);
					this.show();
				}
				else if(mFocusdTextFieldPosition_num != mFocusdTextField_txt.caretIndex)
				{
					mFocusdTextFieldPosition_num = mFocusdTextField_txt.caretIndex;
				}
			}
			
			if (mFocusdTextField_txt != null && mFocusdTextField_txt.stage && TextField(mTimeline_mc.stage.focus) != mFocusdTextField_txt)
			{
				mTimeline_mc.stage.focus = mFocusdTextField_txt;
			}
		}
		
		private function handleGroupSelect():Boolean
		{
			var groupSelected_bol:Boolean = mFocusdTextField_txt.selectionBeginIndex != mFocusdTextField_txt.selectionEndIndex;
			if (groupSelected_bol)
			{
				mCurrentString_str = mCurrentString_str.substring(0, mFocusdTextField_txt.selectionBeginIndex ) + mCurrentString_str.substring(mFocusdTextFieldPosition_num, mCurrentString_str.length);
				
				mFocusdTextFieldPosition_num = mFocusdTextField_txt.selectionBeginIndex;
				mFocusdTextField_txt.setSelection(mFocusdTextFieldPosition_num, mFocusdTextFieldPosition_num);
			
				mFocusdTextField_txt.text = mCurrentString_str;
			}
			return groupSelected_bol;
		}
		
		private function output(pValue_str:String = ""):void
		{
			trace(mCurrentString_str.substring(0, mFocusdTextFieldPosition_num) + " + " + pValue_str + " + " + mCurrentString_str.substring(mFocusdTextFieldPosition_num, mCurrentString_str.length));
			mCurrentString_str = mCurrentString_str.substring(0, mFocusdTextFieldPosition_num) + pValue_str + mCurrentString_str.substring(mFocusdTextFieldPosition_num, mCurrentString_str.length);
			trace("output:" + mCurrentString_str + "|");
			
			mFocusdTextFieldPosition_num += pValue_str.length;
			mFocusdTextField_txt.setSelection(mFocusdTextFieldPosition_num, mFocusdTextFieldPosition_num);
			
			mFocusdTextField_txt.text = mCurrentString_str;
		}
		
		private function onBackSpaceBtnPress():void
		{
			if (!this.handleGroupSelect())
			{
				mCurrentString_str = mCurrentString_str.substring(0, mFocusdTextFieldPosition_num - 1) + mCurrentString_str.substring(mFocusdTextFieldPosition_num, mCurrentString_str.length);
				mFocusdTextFieldPosition_num = Math.max(0, mFocusdTextFieldPosition_num - 1);
				mFocusdTextField_txt.setSelection(mFocusdTextFieldPosition_num, mFocusdTextFieldPosition_num);
				
				this.output();
			}
		}
		
		private function onInputBtnPress(pBtn:VirtualKeyboardLabelButton):void
		{
			var value_str:String;
			
			if(this.isAlphabetElement(pBtn.getLowerCaseValue()))
			{
				value_str = (mShiftKey_bol != mCapsLock_bol)?pBtn.getUpperCaseValue():pBtn.getLowerCaseValue();
			}
			else
			{
				value_str = (mShiftKey_bol)?pBtn.getUpperCaseValue():pBtn.getLowerCaseValue();
			}
			
			if (mShiftKey_bol)
			{
				this.onShiftBtnOff();
			}
			
			this.handleGroupSelect();
			
			this.output(value_str);
		}
		
		private function onKeyUpHandler(e:KeyboardEvent):void
		{
			//mCapsLock_bol = Keyboard.capsLock;
			//mShiftKey_bol = e.shiftKey;
			//
			//this.handleCapsLockAndShiftBtn();
		}
		
		private function onKeyDownHandler(e:KeyboardEvent, pHumanCapsLock_num:Number = 0):void
		{
			//if(pHumanCapsLock_num == 0)
				//mCapsLock_bol = Keyboard.capsLock || mCapsLockBtn.isChecked();
			//else if (pHumanCapsLock_num == 1)
				//mCapsLock_bol = true;
			//else if (pHumanCapsLock_num == -1)
				//mCapsLock_bol = false;
			//
			//mShiftKey_bol = e.shiftKey;
			//
			//this.handleCapsLockAndShiftBtn();
			//
			//if (VirtualKeyboardASCIICollection.getStringFromASCII(e.charCode) != null)
			//{ 
				//VirtualKeyboardLabelButton(mLabelBtn_array[VirtualKeyboardASCIICollection.getStringFromASCII(e.charCode)]).onPress();
			//}
		}
		
		private function onCapsLockBtnOn():void
		{
			//trace("CAPSLOCK on");
			
			mCapsLock_bol = true;
			
			this.handleCapsLockAndShiftBtn();
			
			//mCapsLockBtn.reset();
			//this.onKeyDownHandler(new KeyboardEvent("KEY_DOWN"), 1);
		}
		
		private function onCapsLockBtnOff():void
		{
			//trace("CAPSLOCK off");
			
			mCapsLock_bol = false;
			
			this.handleCapsLockAndShiftBtn();
			
			//mCapsLockBtn.select();
			//this.onKeyDownHandler(new KeyboardEvent("KEY_DOWN"), -1);
		}
		
		private function onShiftBtnOn():void
		{
			//trace("SHIFTKEY on");
			
			mShiftKey_bol = true;
			
			this.handleCapsLockAndShiftBtn();
			
			//mLeftShiftBtn.reset();
			//this.onKeyDownHandler(new KeyboardEvent("KEY_DOWN", true, false, 0, 0, 0, false, false, true));
		}
		
		private function onShiftBtnOff():void
		{
			//trace("SHIFTKEY off");
			
			mShiftKey_bol = false;
			
			this.handleCapsLockAndShiftBtn();
			
			//mLeftShiftBtn.select();
			//this.onKeyDownHandler(new KeyboardEvent("KEY_DOWN", true, false, 0, 0, 0, false, false, false));
		}
		
		private function handleCapsLockAndShiftBtn():void
		{
			//trace("handleCapsLockAndShiftBtn");
			
			//if (mCapsLock_bol != mCapsLockBtn.isChecked())
			if (mCapsLock_bol)
			{
				if (mCapsLock_bol != mShiftKey_bol)
				{
					this.switchAlphabetToUpperLabel();
				}
				else
				{
					this.switchAlphabetToLowerLabel();
				}
			}
			
			//if(mShiftKey_bol != mLeftShiftBtn.isChecked())
			//if(mShiftKey_bol)
			//{
				if (mShiftKey_bol)
				{
					if (mCapsLock_bol)
					{
						this.switchNonAlphabetToUpperLabel();
						this.switchAlphabetToLowerLabel();
					}
					else
					{
						this.switchNonAlphabetToUpperLabel();
						this.switchAlphabetToUpperLabel();
					}
				}
				else
				{
					if (mCapsLock_bol)
					{
						this.switchNonAlphabetToLowerLabel();
						this.switchAlphabetToUpperLabel();
					}
					else
					{
						this.switchNonAlphabetToLowerLabel();
						this.switchAlphabetToLowerLabel();
					}
				}
			//}
			
			//if (mCapsLock_bol)
			//{
				//mCapsLockBtn.check();
			//}
			//else
			//{
				//mCapsLockBtn.uncheck();
			//}
			//
			if (mShiftKey_bol)
			{
				mLeftShiftBtn.check();
				mRightShiftBtn.check();
			}
			else
			{
				mLeftShiftBtn.uncheck();
				mRightShiftBtn.uncheck();
			}
		}
		
		private function switchNonAlphabetToUpperLabel(pDoneCall:ICall = null):void
		{
			for (var i in mLabelBtn_array)
			{
				if (!this.isAlphabetElement(i))
				{
					VirtualKeyboardLabelButton(mLabelBtn_array[i]).switchToUpperCase(pDoneCall);
					pDoneCall = null;
				}
			}
		}
		
		private function switchNonAlphabetToLowerLabel(pDoneCall:ICall = null):void
		{
			for (var i in mLabelBtn_array)
			{
				if (!this.isAlphabetElement(i))
				{
					VirtualKeyboardLabelButton(mLabelBtn_array[i]).switchToLowerCase(pDoneCall);
					pDoneCall = null;
				}
			}
		}
		
		private function switchAlphabetToUpperLabel(pDoneCall:ICall = null):void
		{
			for (var i in mLabelBtn_array)
			{
				if (this.isAlphabetElement(i))
				{
					VirtualKeyboardLabelButton(mLabelBtn_array[i]).switchToUpperCase(pDoneCall);
					pDoneCall = null;
				}
			}
		}
		
		private function switchAlphabetToLowerLabel(pDoneCall:ICall = null):void
		{
			for (var i in mLabelBtn_array)
			{
				if (this.isAlphabetElement(i))
				{
					VirtualKeyboardLabelButton(mLabelBtn_array[i]).switchToLowerCase(pDoneCall);
					pDoneCall = null;
				}
			}
		}
		
		private function isAlphabetElement(pIndex_str:String):Boolean
		{
			return (pIndex_str >= "a" && pIndex_str <= "z") || (pIndex_str >= "A" && pIndex_str <= "Z");
		}
	}

}