package
{
	import flash.display.*;
	import flash.geom.Point;
	import flash.utils.*;

	public class PieceLibrary
	{
		protected var pieces:Array = [];
		
		public function Reset()
		{
			pieces.splice(0);
		}
		
		private function GetArtistGivenName(clipName:String):String
		{
			if (clipName.match(/instance\d+/))
			{
				return null;
			}
			return clipName;
		}
		
		private function GetNextAvailableName(artistName:String):String
		{
			if (artistName == null) return null;
			if (artistName.match("^instance\\d+$")) return null;

			var maxNameCount = 0;
			for (var i in pieces)
			{
				if (pieces[i].Name != null)
				{
					var m = pieces[i].Name.match(new RegExp("^" + artistName + "(\\d+)?$"));
					if (m)
					{
						maxNameCount = Math.max(maxNameCount, m[1] == undefined ? 1 : (Number(m[1]) + 1));
					}
				}
			}
			return artistName + (maxNameCount == 0 ? "" : maxNameCount);
		}
		
		public function GetPieceFromClip(clip:DisplayObject, outCenterPoint:Point, upscale:Number = 1)
		{
			var piece:Piece = GetExistingPiece(Piece.GenerateCompareData(clip), clip.name);
			if (piece != null) return piece;
			
			piece = new Piece();
			var center:Point = piece.InitFromClip(clip, upscale);
			if (piece.Valid)
			{
				piece.Name = GetNextAvailableName(clip.name);
				
				pieces.push(piece);
				outCenterPoint.x = center.x;
				outCenterPoint.y = center.y;
				return piece;
			}
			
			return null;
		}
		
		private function GetExistingPiece(compareData:BitmapData, artistName:String)
		{
			if (compareData == null) return null;
			
			for (var i in pieces)
			{
				if (pieces[i].Matches(compareData, artistName))
				{
					if (pieces[i].Name == null)
					{
						pieces[i].Name = GetNextAvailableName(artistName);
					}
					return pieces[i];
				}
			}
			
			return null;
		}
		
		public function GetPieceFromBitmapData(bd:BitmapData, pieceName:String, centerPoint:Point = null)
		{
			if (centerPoint == null) centerPoint = new Point(0, 0);
			
			var piece:Piece = GetExistingPiece(bd, pieceName);
			if (piece != null) return piece;
			
			piece = new Piece();
			piece.InitFromBitmapData(bd, centerPoint);
			if (piece.Valid)
			{
				piece.Name = GetNextAvailableName(pieceName);
				pieces.push(piece);
				return piece;
			}
			
			return null;
		}
		
		public function Debug()
		{
			var nextX = 0;
			for (var i = 0; i < pieces.length; i++)
			{
				if (pieces[i].TotalUses > 0)
				{
					var b:Bitmap = new Bitmap(pieces[i].FullData);
					b.scaleX = b.scaleY = 1;
					b.x = nextX;
					nextX += b.width;
				}
			}
		}
		
		public function get NumUsedPieces()
		{
			var count = 0;
			for (var i in this.pieces)
			{
				if (pieces[i].TotalUses > 0)
				{
					count++;
				}
			}
			return count;
		}
		
		public function GetAllUsedPieces():Array
		{
			var ret:Array = [];
			for (var i in this.pieces)
			{
				if (pieces[i].TotalUses > 0)
				{
					ret.push(pieces[i]);
				}
			}
			return ret;
		}
		
		public function EnsureAllUsedPiecesHaveNames()
		{
			var index = 0;
			var used:Array = GetAllUsedPieces();
			for (var i in used)
			{
				if (used[i].Name == null) used[i].Name = "UnknownPiece" + (index++);
			}
		}
	}
}