module jg {
	export class BufferedRenderer extends Renderer {
		buffer: HTMLCanvasElement;
		c: CanvasRenderingContext2D;
		size: CommonSize;

		constructor(size:CommonSize) {
			super();
			this.size = size;
			this.refresh();
		}

		clear() {
			this.c.clearRect(0, 0, this.size.width, this.size.height);
		}

		createImage(area?:CommonArea, distArea?:CommonArea, canvasSize?:CommonSize):HTMLCanvasElement {
			if (! area)
				area = {x: 0, y: 0, width: this.size.width, height: this.size.height};
			if (! distArea)
				distArea = {x: 0, y: 0, width: area.width, height: area.height}
			if (! canvasSize)
				canvasSize = area;

			var canvas:HTMLCanvasElement = window.createCanvas(canvasSize.width, canvasSize.height);

			var context = canvas.getContext("2d");
			context.drawImage(
				this.buffer,
				area.x,
				area.y,
				area.width,
				area.height,
				distArea.x,
				distArea.y,
				distArea.width,
				distArea.height
			);
			if (this.filter)
				this.applyFilter(context, distArea);
			return canvas;
		}

		createSprite(area?:CommonArea, distArea?:CommonArea, canvasSize?:CommonSize) {
			if (! area)
				area = {x: 0, y: 0, width: this.size.width, height: this.size.height};
			if (! distArea)
				distArea = {x: 0, y: 0, width: area.width, height: area.height}
			return new Sprite(
				this.createImage(area, distArea, canvasSize),
				area.width,
				area.height
			);
		}

		applyFilter(c:CanvasRenderingContext2D, size:CommonSize) {
			var imageData = c.getImageData(0, 0, size.width, size.height);
			this.filter.filter(imageData);
			c.putImageData(imageData, 0, 0);
		}

		renderUnit(entity:E) {
			var area:CommonArea = {x: 0, y: 0, width: entity.width, height: entity.height}
			this.renderEntity(entity, this.c);
		}

		renderLayer(layer:Layer) {
			this.renderParent(layer, this.c);
		}

		renderScene(scene:Scene) {
			this.clear();
			for (var i in scene.layers) {
				this.c.save();
				var layer = scene.layers[i];
				if (layer.x || layer.y)
					this.c.translate(layer.x, layer.y);
				this.renderLayer(layer);
				this.c.restore();
			}
		}

		refresh() {
			delete this.buffer;
			this.buffer = window.createCanvas(this.size.width, this.size.height);
			this.c = this.buffer.getContext("2d");
		}

		draw(context:CanvasRenderingContext2D) {
			context.drawImage(
				this.buffer,
				0,
				0,
				this.size.width,
				this.size.height,
				0,
				0,
				this.size.width,
				this.size.height
			);
		}
	}
}
