class FindBySize
{
	constructor(width /*int*/, height /*int*/)
	{
		this.width = width;
		this.height = height;
	}

	findPiece(skel /*SkeletalAnimationController*/, frame /*int*/)
	{		
		var best = null;
		var bestScore = null;
		for (var piece of skel.pieces)
		{
			if (piece != null && piece.sequence[frame] != null)
			{
				//var piece = psData.piece.getBitmapInfo(skel);
				var score = Math.abs(piece.w - this.width) + Math.abs(piece.h - this.height);
				if (bestScore == null || score < bestScore)
				{
					best = piece;
					bestScore = score;
				}
			}
		}
		
		return best;
	}
}

class SkeletalAnimationPieceFollower extends Engine.Drawable
{
	constructor()
	{
		super();

		this.target = null;
		this.finder = null;
		this.lastFrame = -1;
		this.lastSeq = -1;
	}

	init(target /*Drawable*/, finder /*PieceFinder*/)
	{
		this.target = target;
		this.finder = finder;
		
		this.lastFrame = -1;
		this.lastSeq = -1;
		
		if (this.target.loaded)
		{
			this.updatePiece(true);
		}
		else
		{
			this.target.onGraphicLoaded.addListener(this, this.targetLoaded);
		}
		
		Engine.EnterFrameManagerInstance.addPostFrame(this, this.postFrameUpdate);
	}

	targetLoaded(d /*Drawable*/)
	{
		d.onGraphicLoaded.removeListener(this, this.targetLoaded);
		this.updatePiece(true);
	}

	updatePiece(force /*bool*/)
	{
		if (this.target == null || this.parent == null/* || !this.attachedToRoot*/) return;
		
		var frame = this.target.frame; //currentFrame
		var seq = this.target.getSequence();
		
		if (force || frame != this.lastFrame || seq != this.lastSeq)
		{
			if (this.target.loaded)
			{
				var skel = this.target.skeletalController;//getSkelAnim();
				if (skel != null)// && skel.currentSequence != null)
				{
					var best = this.finder.findPiece(skel, frame);
					
					if (best != null)
					{
						var bestFrame = best.sequence[frame];
						var pos = this.parent.globalToLocal(this.target.localToGlobal(parseFloat(bestFrame.tx), parseFloat(bestFrame.ty)));
						this.setXYUnrounded(parseFloat(bestFrame.tx), parseFloat(bestFrame.ty));
						
						this.scale.x = parseFloat(bestFrame.sx);
						this.scale.y = parseFloat(bestFrame.sy);
						
						this.rotationDegrees = parseFloat(bestFrame.rot) * -180.0 / Math.PI;
					}
				}
			}
			
			this.lastFrame = frame;
			this.lastSeq = seq;
		}
	}

	postFrameUpdate(timeElapsed /*float*/)
	{
		if (this.hasParent && this.target != null/* && this.attachedToRoot*/)
		{
			this.updatePiece(false);
			
			this.manualAnimationUpdate();
		}
	}

	clear()
	{
		if (this.target != null) this.target.onGraphicLoaded.removeListener(this, this.targetLoaded);
		
		this.target = null;
		this.finder = null;
		
		Engine.EnterFrameManagerInstance.removePostFrame(this);
	}
}