package com.guru.display 
{
	import com.guru.call.ICall;
	import flash.display.MovieClip;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Rectangle;
	
	/**
	 * ...
	 * @author Eddy Lee
	 */
	public class LabelDragButton 
	{
		protected static const LABEL_ENABLE:String = "enable";
		protected static const LABEL_DISABLE:String = "disable";
		protected static const LABEL_NORMAL:String = "normal";
		protected static const LABEL_OVER:String = "over";
		protected static const LABEL_SELECT:String = "select";
		
		protected var mTimeline:MovieClip;
		protected var mIsVisualDisable:Boolean;
		protected var mDisableControl:LabelMovieClip;
		protected var mContentControl:LabelMovieClip;
		protected var mDragStartCall:ICall;
		protected var mDraggingCall:ICall;
		protected var mDragStopCall:ICall;
		protected var mOverCall:ICall;
		protected var mOverDoneCall:ICall;
		protected var mOutCall:ICall;
		protected var mOutDoneCall:ICall;
		
		protected var mHitArea:MovieClip;
		protected var mHitDummy:MovieClip;
		
		protected var mDragArea:Rectangle;
		protected var mDragging:Boolean;
		protected var mPrevX:Number;
		protected var mPrevY:Number;
		
		public function LabelDragButton(pTimeline:MovieClip) 
		{
			mTimeline = pTimeline;
			var mc:MovieClip = mTimeline.getChildByName("btn_mc") as MovieClip || mTimeline;
			
			if (mc != mTimeline) 
			{
				mDisableControl = new LabelMovieClip(mTimeline, LABEL_ENABLE);
			}
			
			mContentControl = new LabelMovieClip(mc, LABEL_NORMAL);
			
			mHitArea = mc.getChildByName("hitArea_mc") as MovieClip || mTimeline.getChildByName("hitArea_mc") as MovieClip || mTimeline;
			mHitArea.addEventListener(MouseEvent.MOUSE_DOWN, onPress, false, 0, true);
			mHitArea.addEventListener(MouseEvent.MOUSE_UP, onRelease, false, 0, true);
			mHitArea.addEventListener(MouseEvent.ROLL_OVER, onOver, false, 0, true);
			mHitArea.addEventListener(MouseEvent.ROLL_OUT, onOut, false, 0, true);
			mHitArea.buttonMode = true;
			addHitDummy();
			
			mDragArea = new Rectangle();
			try 
			{
				enabled = (mDisableControl.getTimeline().currentLabel == LABEL_ENABLE);
			}
			catch (e:Error)
			{
				enabled = true;
			}
			visualDisable = true;
		}
		
		public function getTimeline():MovieClip 
		{
			return (mDisableControl)? mDisableControl.getTimeline() : getInnerTimeline();
		}
		
		public function getInnerTimeline():MovieClip 
		{
			return mContentControl.getTimeline();
		}
		
		public function get enabled():Boolean 
		{
			return mHitArea.mouseEnabled;
		}
		
		public function set enabled(pValue:Boolean):void 
		{
			mHitArea.mouseEnabled = pValue;
			mHitArea.mouseChildren = pValue;
			updateVisualDisable(); 
		}
		
		public function set visualDisable(pValue:Boolean):void 
		{
			mIsVisualDisable = pValue;
			updateVisualDisable();
		}
		
		public function set useHandCursor(pValue:Boolean):void 
		{
			mHitArea.useHandCursor = pValue;
		}
		
		public function setDragableArea(pDragArea:Rectangle):void 
		{
			mDragArea = pDragArea.clone();
		}
		
		public function setDragStartCall(pCall:ICall):void 
		{
			mDragStartCall = pCall;
		}
		
		public function setDraggingCall(pCall:ICall):void 
		{
			mDraggingCall = pCall;
		}
		
		public function setDragStopCall(pCall:ICall):void 
		{
			mDragStopCall = pCall;
		}
		
		public function setOverCall(pCall:ICall):void 
		{
			mOverCall = pCall;
		}
		
		public function setOverDoneCall(pCall:ICall):void 
		{
			mOverDoneCall = pCall;
		}
		
		public function setOutCall(pCall:ICall):void 
		{
			mOutCall = pCall;
		}
		
		public function setOutDoneCall(pCall:ICall):void 
		{
			mOutDoneCall = pCall;
		}
		
		public function normal():void 
		{
			playToNormal();
		}
		
		public function reset():void 
		{
			enabled = true;
			normal();
		}
		
		public function onPress(pEvent:MouseEvent = null):void 
		{
			if (enabled) 
			{
				onDragStart();
				playToSelect();
			}
		}
		
		public function onRelease(pEvent:MouseEvent = null):void 
		{
			if (enabled) 
			{
				onDragStop();
				playToOver();
			}
		}
		
		public function onReleaseOutside(pEvent:MouseEvent = null):void 
		{
			if (enabled) 
			{
				mHitArea.stage.removeEventListener(MouseEvent.MOUSE_UP, onReleaseOutside);
				onDragStop();
				playToNormal();
			}
		}
		
		public function onOver(pEvent:MouseEvent = null):void 
		{
			if (enabled) 
			{
				if (!mDragging) 
				{
					playToOver(mOverDoneCall);
					try 
					{
						mOverCall.execute();
					} catch (e:Error) { }
				}
				
				else 
				{
					mHitArea.stage.removeEventListener(MouseEvent.MOUSE_UP, onReleaseOutside);
				}
			}
		}
		
		public function onOut(pEvent:MouseEvent = null):void 
		{
			if (enabled) 
			{
				if (!mDragging) 
				{
					playToNormal(mOutDoneCall);
					try 
					{
						mOutCall.execute();
					} catch (e:Error) { }	
				}
				
				else 
				{
					mHitArea.stage.addEventListener(MouseEvent.MOUSE_UP, onReleaseOutside, false, 0, true);
				}
			}
		}
		
		public function dispose():void 
		{
			removeHitDummy();
			mHitArea.buttonMode = false;
			mHitArea.stage.removeEventListener(MouseEvent.MOUSE_UP, onReleaseOutside);
			mHitArea.stage.removeEventListener(MouseEvent.MOUSE_MOVE, onDragging);
			mHitArea.removeEventListener(MouseEvent.MOUSE_DOWN, onPress);
			mHitArea.removeEventListener(MouseEvent.MOUSE_UP, onRelease);
			mHitArea.removeEventListener(MouseEvent.ROLL_OUT, onOut);
			mHitArea.removeEventListener(MouseEvent.ROLL_OVER, onOver);
			mHitArea = null;
			mTimeline = null;
			mDragArea = null;
			
			try 
			{
				mDisableControl.dispose();
			} catch (e:Error) { }
			mDisableControl = null;
			mContentControl.dispose();
			mContentControl = null;
			
			mDragStartCall = null;
			mDraggingCall = null;
			mDragStopCall = null;
			mOverCall = null;
			mOverDoneCall = null;
			mOutCall = null;
			mOutDoneCall = null;
		}
		
		protected function onDragStart():void 
		{
			try 
			{
				mDragStartCall.execute();
			} catch (e:Error) { }
			
			mPrevX = mTimeline.x;
			mPrevY = mTimeline.y;
			
			mTimeline.startDrag(false, mDragArea);
			mDragging = true;
			mHitArea.stage.addEventListener(MouseEvent.MOUSE_MOVE, onDragging, false, 0, true);
		}
		
		protected function onDragging(pEvent:MouseEvent):void 
		{
			var newX:Number = mTimeline.x;
			var newY:Number = mTimeline.y;
			var deltaX:Number = newX - mPrevX;
			var deltaY:Number = newY - mPrevY;
			mPrevX = newX;
			mPrevY = newY;
			
			if (deltaX != 0 || deltaY != 0) 
			{
				try 
				{
					mDraggingCall.execute();
				} catch (e:Error) { }
			}
		}
		
		protected function onDragStop():void 
		{
			mTimeline.stopDrag();
			mDragging = false;
			mHitArea.stage.removeEventListener(MouseEvent.MOUSE_MOVE, onDragging);
			try 
			{
				mDragStopCall.execute();
			} catch (e:Error) { }
		}
		
		protected function updateVisualDisable():void 
		{
			try 
			{
				mDisableControl.playTo((mIsVisualDisable && !enabled)? LABEL_DISABLE : LABEL_ENABLE);
			} catch (e:Error) { }
		}
		
		protected function playToNormal(pCall:ICall = null):void 
		{
			mContentControl.playTo(LABEL_NORMAL, pCall);
		}
		
		protected function playToOver(pCall:ICall = null):void 
		{
			mContentControl.playTo(LABEL_OVER, pCall);
		}
		
		protected function playToSelect(pCall:ICall = null):void 
		{
			mContentControl.playTo(LABEL_SELECT, pCall);
		}
		
		protected function addHitDummy():void 
		{
			if (mHitArea.stage) 
			{
				mHitArea.addEventListener(Event.ENTER_FRAME, removeHitDummy, false, 0, true);
				mHitDummy = new mHitArea.constructor();
				mHitDummy.transform.matrix = mHitArea.transform.matrix;
				mHitDummy.alpha = 0;
				mHitArea.parent.addChild(mHitDummy);
			}	
		}
		
		protected function removeHitDummy(pEvent:Event = null):void 
		{
			try 
			{
				mHitArea.removeEventListener(Event.ENTER_FRAME, removeHitDummy);
				mHitDummy.parent.removeChild(mHitDummy);
				mHitDummy = null;
			} catch (e:Error) { }
		}
	}
	
}