enum CharacterAngle {
	left,
	right,
	up,
	down
}
interface CharacterMoveInfo {
	x:number;
	y:number;
	dx:number;
	dy:number;
	f:number;
	t:number;
}
interface CharacterMovedEventArgs {
	nextMove?: string;
}
class Character extends Sprite {
	moving:bool;
	moveInfo:CharacterMoveInfo;
	dx:number;
	dy:number;
	nextMove:string;
	moved:Trigger;

	constructor(width:number, height:number, image:HTMLImageElement, wait?:number) {
		super(width, height, image);

		this.moving = false;
		if (! wait)
			wait = 200;

		this.startTimer(wait);
	}

	moveLeft(stackNext?:bool) {
		if (this.move(-64, 0, 20)) {
			this.angle(CharacterAngle.left);
			return true;
		}
		if (stackNext && this.moveInfo.t*2 >= this.moveInfo.f)
			this.nextMove = "Left";
		return false;
	}

	moveRight(stackNext?:bool) {
		if (this.move(64, 0, 20)) {
			this.angle(CharacterAngle.right);
			return true;
		}
		if (stackNext && this.moveInfo.t*2 >= this.moveInfo.f)
			this.nextMove = "Right";
		return false;
	}

	moveUp(stackNext?:bool) {
		if (this.move(0, -64, 20)) {
			this.angle(CharacterAngle.up);
			return true;
		}
		if (stackNext && this.moveInfo.t*2 >= this.moveInfo.f)
			this.nextMove = "Up";
		return false;
	}

	moveDown(stackNext?:bool) {
		if (this.move(0, 64, 20)) {
			this.angle(CharacterAngle.down);
			return true;
		}
		if (stackNext && this.moveInfo.t*2 >= this.moveInfo.f)
			this.nextMove = "Down";
		return false;
	}

	move(x:number, y:number, f:number) {
		if (this.moving)
			return false;
		this.moving = true;
		this.moveInfo = {
			x: this.x,
			y: this.y,
			dx: this.x + x,
			dy: this.y + y,
			f: f,
			t: 0
		}
		this.dx = x;
		this.dy = y;

		this.start();

		return true;
	}

	update() {
		if (this.moving) {
			this.moveInfo.t++;
			if (this.moveInfo.t < this.moveInfo.f) {
				this.moveTo(
					this.moveInfo.x + Math.round((this.moveInfo.dx - this.moveInfo.x) / this.moveInfo.f * this.moveInfo.t),
					this.moveInfo.y + Math.round((this.moveInfo.dy - this.moveInfo.y) / this.moveInfo.f * this.moveInfo.t)
				);
			} else if (this.moveInfo.t == this.moveInfo.f) {
				this.moveTo(this.moveInfo.dx, this.moveInfo.dy);
				this.endMove();
			}
		}
	}

	endMove() {
		this.moving = false;
		this.stop();
		var e:CharacterMovedEventArgs = {}
		if (this.nextMove) {
			e.nextMove = this.nextMove
			;
			delete this.nextMove;
		}
		if (this.moved)
			this.moved.fire(e);
		if (e.nextMove) {
			this["move"+e.nextMove]();
		}
	}

	angle(angle:CharacterAngle) {
		var f;
		switch (angle) {
		case CharacterAngle.up:
			f = 3 * 3;
		break;
		case CharacterAngle.down:
			f = 0 * 3;
		break;
		case CharacterAngle.left:
			f = 3  * 1;
		break;
		case CharacterAngle.right:
			f = 3 * 2;
		break;
		}
		this.frame = [0+f, 1+f, 2+f, 1+f];
	}

	interval() {
		this.fno = (this.fno+1) % this.frame.length;
		this.updated();
	}
}
