package 
{
	import flash.display.*;
	import flash.events.*;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.utils.Timer;
	
	public class ScrollBar
	{
		public static const H = "H";
		public static const L = "L";
		
		public const name = "滚动条窗口";
		
		private var _speed:Number = 15;
		private var _upBtn:Sprite;
		private var _downBtn:Sprite;
		
		private var _tween:Number;
		private var _elastic:Boolean;
		private var _lineAbleClick:Boolean;
		private var _mouseWheel:Boolean;
		private var _direction:String;
		private var _scale9Grid:Rectangle;

		private var _target:DisplayObject;
		private var _maskTarget:DisplayObject;
		private var _scrollBar:Sprite;
		private var _scrollLine:Sprite;
		
		private var _timer:Timer = null;
		private var _scrollBarOriginalPoint:Point;
		private var _parentMC:DisplayObjectContainer;
		private var _rectangle:Rectangle;
		private var _distanceX:Number;
		private var _distanceY:Number;
		private var _targetPoint:Number = NaN;
		
		private var _coor:String;
		private var _length:String;
		private var _mouse:String;
		private var _oldLength:Point;
		private var _abled = true;
		
		public function set tween($value:Number):void
		{
			_tween = $value < 1||$value > 20?1:$value;
		}
		
		public function set elastic($value:Boolean):void
		{
			_elastic = $value ;
			if (_abled)
			makeScrollBar();    
		}
		
		public function set lineAbleClick($value:Boolean):void
		{
			_lineAbleClick = $value ;
			if (_lineAbleClick)
			_scrollLine.addEventListener(MouseEvent.MOUSE_DOWN,              scrollLineMouseDownHandler, false, 0, true );	
			else 
			_scrollLine.removeEventListener(MouseEvent.MOUSE_DOWN,              scrollLineMouseDownHandler);	
		}
		
		public function set mouseWheel($value:Boolean):void
		{
			_mouseWheel = $value ;
			if (_mouseWheel && _abled)
			_parentMC.stage.addEventListener(MouseEvent.MOUSE_WHEEL, mouseWheelHandler, false, 0, true );
			else if(_abled)
			_parentMC.stage.removeEventListener(MouseEvent.MOUSE_WHEEL, mouseWheelHandler);
		}
			
		public function set direction($value:String):void
		{
			_direction = $value ;
			_coor = _direction == "H"?"x":"y";
			_length = _coor == "x"?"width":"height";
			_mouse = _coor == "x"?"mouseX":"mouseY";
			
			if (_abled)
			makeScrollBar();  
		}
		
		public function set scale9Grid($value:Rectangle):void
		{
			_scale9Grid = $value ;
			try { _scrollBar.scale9Grid =  _scale9Grid } catch (e) { _scrollBar.scale9Grid = null }
		}
		
		public function set speed($value:Number):void
		{
			_speed = $value<5||$value>35?15:$value;
		}
		
		public function set UP($target:Sprite):void
		{
			_upBtn = $target;
			if (!_abled)
			{
				_upBtn.visible = false;
				_upBtn.removeEventListener(MouseEvent.MOUSE_DOWN, upDownBtnMouseDownHandler );
				return;
			}
			_upBtn.addEventListener(MouseEvent.MOUSE_DOWN, upDownBtnMouseDownHandler, false, 0, true );
		}
		
		public function set DOWN($target:Sprite):void
		{
			_downBtn = $target;
			if (!_abled)
			{
				_downBtn.visible = false;
				_downBtn.removeEventListener(MouseEvent.MOUSE_DOWN, upDownBtnMouseDownHandler );
				return;
			}
			_downBtn.addEventListener(MouseEvent.MOUSE_DOWN, upDownBtnMouseDownHandler, false, 0, true );
		}
		
		/**
		* 双向(横板+竖版)滚动条
		* @param		$target		      	  	DisplayObjectContainer		 * 被遮罩对象
		* @param		$maskTarget		        *		        			 * 遮罩对象(可传入Rectangle类型)
		* @param		$scrollBar		        Sprite		     		     * 滚动滑块
		* @param		$scrollLine		        Sprite		      			 * 滚动条
		* @param		$tween		            Number		         		 * 缓动系数
		* @param		$elastic		        Boolean		       			 * 滑块可否拉伸
		* @param		$lineAbleClick		    Boolean		      	         * 滚动条可否点击
		* @param		$mouseWheel		   		Boolean		      	         * 滚轮可用
		* @param		$direction		    	String		      	         * 方向(默认纵向)
		*/  
		public function ScrollBar($target:DisplayObjectContainer, $maskTarget:*, $scrollBar:Sprite, $scrollLine:Sprite, $tween:Number = 0, $elastic:Boolean = true, $lineAbleClick:Boolean = false, $mouseWheel:Boolean = true, $direction:String = "L") 
		{
			if (!(($maskTarget is DisplayObject) || ($maskTarget is Rectangle))) throw(new Error("没有传入遮罩对象"));
			
			_target = $target;
			_maskTarget = $maskTarget is Rectangle?drawMaskTarget($maskTarget):$maskTarget;
			_scrollBar = $scrollBar;
			_scrollLine = $scrollLine;
			_tween = $tween < 1||$tween > 20?1:$tween;
			_elastic = $elastic;
			_lineAbleClick = $lineAbleClick;
			_mouseWheel = $mouseWheel;
			_direction = $direction;
			_parentMC = _scrollBar.parent;
			_coor = $direction == "H"?"x":"y";
			_length = _coor == "x"?"width":"height";
			_mouse = _coor == "x"?"mouseX":"mouseY";
			_oldLength = new Point(_scrollBar.width, _scrollBar.height);			
			makeScrollPane();
		}
		
		/**
		* 刷新UI
		*/  
		public function refresh():void
		{
			checkAbled();
		}
		
		private function makeScrollPane():void
		{
			initAllThing();
			_scrollBarOriginalPoint = new Point(_scrollBar.x, _scrollBar.y);
			makeMask();
			checkAbled();	
		}
		
		//检查可用性
		private function checkAbled():void
		{
			_scrollBar.y = _scrollLine.y;
			if (_maskTarget[_length] >= _target[_length])
			{
				_scrollBar.visible = false;
				_scrollLine.visible = false;
				if (_downBtn)_downBtn.visible = false;
				if (_upBtn)_upBtn.visible = false;
				_abled = false;
				
				if (_upBtn&&_downBtn) {
					_upBtn.removeEventListener(MouseEvent.MOUSE_DOWN, upDownBtnMouseDownHandler );
					_downBtn.removeEventListener(MouseEvent.MOUSE_DOWN, upDownBtnMouseDownHandler );
				}
				if (_mouseWheel) makeMouseWheel("stop");
			}else
			{
				_scrollBar.visible = true;
				_scrollLine.visible = true;
				if (_downBtn)_downBtn.visible = true;
				if (_upBtn)_upBtn.visible = true;
				_abled = true;
				
				makeScrollBar(); 
				if (_upBtn&&_downBtn) {
					_upBtn.addEventListener(MouseEvent.MOUSE_DOWN, upDownBtnMouseDownHandler, false, 0, true );
					_downBtn.addEventListener(MouseEvent.MOUSE_DOWN, upDownBtnMouseDownHandler, false, 0, true );
				}
				if (_lineAbleClick) makeScrollLine();
				if (_mouseWheel) makeMouseWheel();
				timeListener();	
			}
		}
		
		//timer检测器
		private function timeListener():void
		{
			if (_timer != null) return;
			_timer = new Timer(1000 / 30, 0);
			_timer.addEventListener(TimerEvent.TIMER, timeHandler, false, 0, true );
			_timer.start();
		}
		
		//注册点
		private function initAllThing():void
		{
			setRegistration(_maskTarget as DisplayObjectContainer);
			setRegistration(_target as DisplayObjectContainer);
			setRegistration(_scrollLine);
			setRegistration(_scrollBar);
		}
		
		//初始化遮罩
		private function makeMask():void
		{
			_target.x = Math.floor(_target.x);                                //防止文字模糊
			_target.y = Math.floor(_target.y);
			_maskTarget.x = _target.x;
			_maskTarget.y = _target.y;
			if (_maskTarget.parent == null)_parentMC.addChild(_maskTarget);
			_target.mask = _maskTarget;
			/*
			GaiaDebug.warn("mask:h"+_target.mask.height+",w"+_target.mask.width+",x"+_target.mask.x+",y"+_target.mask.y);
			GaiaDebug.warn("target:h" + _target.height + ",w" + _target.width + ",x" + _target.x + ",y" + _target.y);		
			*/
		}
		
		//背景条
		private function makeScrollLine():void
		{
			_scrollLine.buttonMode = false;
			_scrollLine.addEventListener(MouseEvent.MOUSE_DOWN,              scrollLineMouseDownHandler, false, 0, true );	
		}
		
		//滚轮
		private function makeMouseWheel(state:String = "start" ):void
		{
			if(state=="start")
			_parentMC.stage.addEventListener(MouseEvent.MOUSE_WHEEL, mouseWheelHandler, false, 0, true );
			else if (state == "stop")
			_parentMC.stage.removeEventListener(MouseEvent.MOUSE_WHEEL, mouseWheelHandler);
		}
		
		//滑块
		private function makeScrollBar():void 
		{
			_scrollBar.buttonMode = true;
			_scrollBar.mouseChildren = false;
			scrollBarLength();                                                  	 //计算滑块长度
			if (_coor == "y")
			_rectangle = new Rectangle(_scrollBarOriginalPoint.x, _scrollBarOriginalPoint.y, 0, _scrollLine.getRect(_parentMC)[_length] - _scrollBar.getRect(_parentMC)[_length]);
			else 
			_rectangle = new Rectangle(_scrollBarOriginalPoint.x, _scrollBarOriginalPoint.y, _scrollLine.getRect(_parentMC)[_length] - _scrollBar.getRect(_parentMC)[_length], 0);
			
			_scrollBar.addEventListener(MouseEvent.MOUSE_DOWN,              scrollBarMouseDownHandler );
			_scrollBar.addEventListener(MouseEvent.MOUSE_UP,                scrollBarMouseUpHandler);
			_scrollBar.parent.stage.addEventListener(MouseEvent.MOUSE_UP,   scrollBarMouseUpHandler);
			_scrollBar.root.stage.addEventListener(Event.MOUSE_LEAVE,       scrollBarMouseUpHandler);
		}
		
		//计算滑块长度
		private function scrollBarLength():void
		{
			if (_elastic)
			try { _scrollBar.scale9Grid =  _scale9Grid } catch (e) {  _scrollBar.scale9Grid = null }
			else
			_scrollBar.scale9Grid = null;
			
			_scrollBar.width = _oldLength.x;
			_scrollBar.height = _oldLength.y;
			_scrollBar[_length] = _elastic ? _scrollLine[_length] * _maskTarget[_length] / _target[_length] : _oldLength[_coor];
		}
		
		private function scrollBarMouseDownHandler(e:MouseEvent):void
		{
			_distanceX = _scrollBar.x - _parentMC.mouseX;
			_distanceY = _scrollBar.y - _parentMC.mouseY;
			_scrollBar.addEventListener(Event.ENTER_FRAME, scrolBarEnterFrameHandler);
		}
		
		private function scrollBarMouseUpHandler(e:*):void
		{
			_scrollBar.removeEventListener(Event.ENTER_FRAME, scrolBarEnterFrameHandler);
		}
		
		private function scrolBarEnterFrameHandler(e:Event):void
		{
			makeDragBar();
		}
		
		private function timeHandler(e:TimerEvent):void
		{
			scrollMachine();
		}
		
		//滚动条点击
		private function scrollLineMouseDownHandler(e:MouseEvent):void
		{
			if (_parentMC[_mouse] > _scrollBar[_coor])
			_scrollBar[_coor] += 3*_speed;
			else
			_scrollBar[_coor] -= 3*_speed;
			judgeBoundary();
		}
		
		//上下按钮点击
		private function upDownBtnMouseDownHandler(e:MouseEvent):void
		{
			if (e.currentTarget == _downBtn)
			_scrollBar[_coor] += 3*_speed;
			else
			_scrollBar[_coor] -= 3 * _speed;
			judgeBoundary();
		}
		
		//鼠标滚轮
		private function mouseWheelHandler(e:MouseEvent):void
		{
			if (e.delta < 0)
			_scrollBar[_coor] += _speed;
			else
			_scrollBar[_coor] -= _speed;
			judgeBoundary();
		}
		
		//拖动滑块
		private function makeDragBar():void
		{
			_scrollBar.x = _parentMC.mouseX + _distanceX;
			_scrollBar.y = _parentMC.mouseY + _distanceY;
			judgeBoundary();	
		}
		
		//判断边界 
		private function judgeBoundary() :void
		{
			if (_scrollBar.x < _rectangle.x)
			_scrollBar.x = _rectangle.x;
			if (_scrollBar.x > _rectangle.right)
			_scrollBar.x = _rectangle.right;
			if (_scrollBar.y < _rectangle.y )
			_scrollBar.y = _rectangle.y;
			if (_scrollBar.y > _rectangle.bottom)
			_scrollBar.y = _rectangle.bottom;
		}
		
		//滚动计算公式
		private function scrollMachine():void
		{
			_targetPoint = _maskTarget[_coor] - (_scrollBar[_coor] - _scrollBarOriginalPoint[_coor]) * (_target[_length] - _maskTarget[_length]) / (_scrollLine[_length] - _scrollBar[_length]);
			if (Math.abs(_target[_coor] - _targetPoint) < .3)
			{
				if (_target[_coor] != _targetPoint) _target[_coor] = _targetPoint;
				return;
			}
			
			if (_tween != 0)
			_target[_coor] += (_targetPoint - _target[_coor]) / _tween; 
			else
			_target[_coor] = _targetPoint;
		}
		
		//绘制遮罩
		private function drawMaskTarget($rect:Rectangle):Sprite
		{
			var maskTarget:Sprite = new Sprite();
			maskTarget.graphics.beginFill(0xffffff);
			maskTarget.graphics.drawRect($rect.x, $rect.y, $rect.width, $rect.height);
			maskTarget.graphics.endFill();
			return maskTarget;
		}
		
		//注册点移到左上角
		private function setRegistration($target:DisplayObjectContainer):void
		{
			var rect = $target.getRect($target);
			var _x = rect.x;
			var _y = rect.y;
			var depth:Number = $target.numChildren;
			if (depth == 0) return;	
			for (var i:uint = 0; i < depth; i++ )
			{
				var target:DisplayObject = $target.getChildAt(i);
				target.x -= _x;
				target.y -= _y;
			}
			if ($target.parent != null)
			{
				$target.x += _x;
				$target.y += _y;
			}
		}
	}
	
}