package com.netgrind.core {
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.display.Stage;
	import flash.events.Event;
	import flash.geom.Rectangle;
	import flash.utils.*;
	import flash.geom.Point;
	
	/**
	 * ...
	 * @author Cale Bradbury(@netgrind)
	 */
	public class Utils{
				
		public static function byteArray2XML(b:ByteArray):XML{
			var ba:ByteArray = b;			
			return new XML(ba.readUTFBytes(ba.length));			
		}
		
		static public function removeChild(mc:DisplayObject, removeSubChildren:Boolean = true ):void 
		{
			if (!mc) {
				return;
			}
			if (removeSubChildren && mc is DisplayObjectContainer) {
				removeAllChildrenIn(mc as DisplayObjectContainer);
			}
			if (mc.parent) {
				mc.parent.removeChild(mc);
			}
		}
		
		public static function getClass(obj:Object):Class{ 
			return Class(getDefinitionByName(getQualifiedClassName(obj)));
		}//end getClass
		
		public static function getObjectAtPointInMovieClip(p:Point, parent:MovieClip, exclude:Array = null):MovieClip {
			if (exclude == null) {
				exclude = [];
			}
			for (var i:int = 0; i < parent.numChildren; i ++ ) {
				if(exclude.indexOf(parent.getChildAt(i))==-1){
					if (parent.getChildAt(i).x == p.x && parent.getChildAt(i).y == p.y) {
						return(MovieClip(parent.getChildAt(i)));
					}//edn if
				}//enmd if
			}//end for
			return null;
		}//edn getObjectAtPoint
		
		public static function getObjectAtPointInArray(p:Point, array:Array, exclude:Array = null):MovieClip {
			if (exclude == null) {
				exclude = [];
			}
			for (var i:int = 0; i < array.length; i ++ ) {
				if(exclude.indexOf(array[i])==-1){
					if (array[i].x == p.x &&  array[i].y == p.y) {
						return(MovieClip(array[i]));
					}//edn if
				}//end if
			}//end for
			return null;
		}//edn getObjectAtPoint
				
		public static function generateNumberArray(num1:int, num2:int, step:int ):Array {
			if(num1>num2){
				step *=-1;
			}//edn if
			var points:Array = new Array();
			points.push(num1);
			do{
				points.push(int(points[points.length-1]+step));
			}while(Math.abs(int(points[points.length-1]-num2))>Math.abs(step));
			return(points);
		}//end generateXArray
		
		public static function checkCollisionAgainstArray(mc:MovieClip,mcArray:Array,usePoint:Boolean = true):Array{
			var touching:Array = new Array();
			for each(var a:MovieClip in mcArray){
				if(usePoint){
					if(a.hitTestPoint(mc.x,mc.y,true)){
						touching.push(a);
					}//end if
				}else{
					if(a.hitTestObject(mc)){
						touching.push(a);
					}//end if
				}//edn if
			}//end for
			return touching;
		}//edn checkCollisionAgainstArray
		
		public static function removeCharacters(s:String):int {
			var a:String = "";
			for (var i:int = 0; i < s.length; i++) {
				if (isDigit(s.charAt(i))) {
					a += s.charAt(i);
				}//end if
			}//end for
			if (a.length == 0) {
				return 0;
			}
			return int(a);
		}//end removeCharacters
		
		public static function isDigit(s:String):Boolean {
			if (s.charCodeAt() > 47 && s.charCodeAt() < 58) {
				return true;
			}//end if
			return false;
		}//end isDigit
		
		public static function getDistance(mc1:Object, mc2:Object):Number {
			return Math.sqrt(Math.pow((mc2.x-mc1.x),2)+Math.pow((mc2.y-mc1.y),2));
		}//edn getDistance
		
		public static function getDistancePoint(mc1:Point, mc2:Point):Number {
			return Math.sqrt(Math.pow((mc2.x-mc1.x),2)+Math.pow((mc2.y-mc1.y),2));
		}//edn getDistance
		
		public static function stringToBoolean(s:String):Boolean {
			if (s == "true") {
				return true;
			}
			return false;
		}//edn stringtoboolean
		
		public static function getAngle(X1:Number, Y1:Number, X2:Number, Y2:Number):Number{
			var dir:Number = radToDeg(Math.atan2((Y2 - Y1), (X2 - X1)));
			return dir;
		}//edn getAngle
		
		public static function radToDeg(radians:Number):Number{
			var degrees:Number = (180/Math.PI)*radians;
			return degrees;
		}//end radtodeg
		
		public static function degToRad(degrees:Number):Number {
			return degrees/(180 / Math.PI);
		}//end degToRad
		
		public static function getPointFromAngle(angle:Number, distance:Number, center:Point ):Point {
			var theta:Number = degToRad(angle);
			return new Point(center.x+(distance * Math.cos(theta)), center.y+(distance * Math.sin(theta)));
		}//end getPointFromAngle
		
		public static function fillArray(length:int, object:Object):Array {
			var a:Array = new Array();
			for (var i:int = 0; i < length; i++) {
				a[i] = object;				
			}//end for
			return a;
		}//edn fillArray
		
		static public function removeAllChildrenIn(obj:DisplayObjectContainer, recurseive:Boolean = true):void {
			while (obj.numChildren!=0) {
				var mc:* = obj.getChildAt(0);
				if (recurseive && mc is DisplayObjectContainer && mc.numChildren != 0) {
					removeAllChildrenIn(mc);
				}
				obj.removeChild(mc);
			}
		}
		
		static public function isPointInRect(p:Point, r:Rectangle):Boolean {
			if (p.x > r.x && p.x < r.x + r.width && p.y > r.y && p.y < r.y + r.height) {
				return true
			}
			return false;
		}
		
		static public function makePoint(obj:*):Point {
			if (obj.x && obj.y) {
				return new Point(obj.x, obj.y);
			}
			return new Point(0,0);
		}
		
		
		
		static public function nextLargestSquare(i:int):int {
			i--;
			i |= i >> 1;
			i |= i >> 2;
			i |= i >> 4;
			i |= i >> 8;
			i |= i >> 16;
			i++
			return i
		}
		
		static public function flipBoolean(obj:*,bool:String):void {
			if (obj[bool] == null) return;
			obj[bool] = !obj[bool];
		}
		
		static public function stretchBitmapWithStage(bitmap:Bitmap, stage:Stage):void {
			stage.addEventListener(Event.RESIZE, strech);
			strech();
			function strech():void {
				if (bitmap.bitmapData) {
					bitmap.bitmapData.dispose();
				}
				bitmap.bitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, true, 0);
			}
		}
		
		static public function contains(rect:*, point:*):Boolean {
			if (Math.min(rect.x, rect.x + rect.width) <= point.x
			&& Math.max(rect.x, rect.x + rect.width) >= point.x
			&&Math.min(rect.y, rect.y + rect.height) <= point.y
			&& Math.max(rect.y, rect.y + rect.height) >= point.y) return true;
			return false;
		}
		
		static public function callAllFunctions(onUpdate:Vector.<Function>):void {
			for (var i:int = 0; i < onUpdate.length; i++) {
				onUpdate[i].call();
			}
		}
		
		static public function xor(lhs:Boolean, rhs:Boolean):Boolean {
			return !( lhs && rhs ) && ( lhs || rhs );
		}
		
		static public function toggleFunction(b:Boolean):Function {
			return function():void { b = !b };
		}
		
		static public function lerp(a:Number, b:Number, l:Number):Number {
			return (1 - l) * a + l * b;
		}
		
		static public function durationAtSpeed(distance:Number,pixelsPerSecond:int):Number {
			
			var duration:Number = Math.abs(distance / pixelsPerSecond);
			return duration;
		}
		
	}
	
}