package
{
	public class FramePacker
	{
		private var frames:Array;	// [FrameInfo]
		public void Pack(frames:Array)
		{
			this.frames = frames.filter(function(i:FrameInfo) { return i.frame != null; });
		}
		
		public function DetermineMinimumSheetSizeForClips(frames:Array):Point
		{

			/* TODO - FOR LARGE SIZED CHUNKS BETTER HANDLING FOR FINDING MINIMUM SIZE! */
			
			var areas:Array = new Array();
			
			for (var i = 0; i < frames.length; i++)
			{
				are
			}
			var areas:Array = frames.map(function(i:FrameInfo) { return i.frame.width * i.frame.height; });
			var maxW = Math.max.apply(Math, frames.map(function(i:FrameInfo) { return i.frame.width; }));
			var maxH = Math.max.apply(Math, frames.map(function(i:FrameInfo) { return i.frame.height; }));
			var max = Math.max(maxW, maxH);
			
			var sorted:Array = areas.sort(Array.RETURNINDEXEDARRAY | Array.NUMERIC | Array.DESCENDING);

			var exponent = Math.ceil(Math.log(max) / Math.log(2));
			max = Math.pow(2, exponent);
			
			//rough heuristic to see if this process is worth doing. 
			//it can be slow if there are a large number of big clips.
			if (frames.length > 100 && max >= 512)
			{
				var s = Math.max(max, 1024);
				return new Point(s, s);
			}
				
			sheets.push(new SpriteSheet(2048, 2048));
			for (var i = 0; i < frames.length; i++)
			{
				var sprite:TextureSprite = new TextureSprite(clips[sorted[i]], CACHESEQUENCES);
				CacheClip(clips[sorted[i]], sprite);
				sprites.push(sprite);
			}
			
			var allUsedRects:Array = new Array();
			var nodesToVisit:Array = new Array();
			for (var i = 0; i < sheets.length; i++)
			{
				var sheet:SpriteSheet = sheets[i];
				var nodes = sheet.GetAllocator().GetLeafNodes();
				for (var n = 0; n < nodes.length; n++)
				{
					allUsedRects.push(nodes[n].Rect);
				}
			}
			
			var sizeFound = false;
			var sheetSizeX = 64;
			var sheetSizeY = 64;
			while(!sizeFound)
			{
				var sheet:SpriteSheet = new SpriteSheet(sheetSizeX, sheetSizeY);
				sizeFound = true;
				for(var i = 0; i < allUsedRects.length; i++)
				{
					var node:RectangleNode = sheet.GetAllocator().Insert(allUsedRects[i].width, allUsedRects[i].height);
					if (node == null)
					{
						sizeFound = false;
						break;
					}
				}
				if (sizeFound == false)
				{
					if (sheetSizeX == sheetSizeY)
					{
						sheetSizeX *= 2;
					}
					else
					{
						sheetSizeY *= 2;
					}
				}
			}
			return new Point(sheetSizeX, sheetSizeY);
		}
	}
}