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?:Area, distArea?:Area):HTMLCanvasElement {
		if (! area)
			area = new Area(0, 0, this.size.width, this.size.height);
		if (! distArea)
			distArea = new Area(0, 0, area.width, area.height)

		var canvas:HTMLCanvasElement = window.createCanvas(area.width, area.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, area);
		return canvas;
	}

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

	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 = new Area(
			0,
			0,
			entity.width,
			entity.height
		);
		this.renderEntity(area, entity, this.c);
	}

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

	renderScene(scene:Scene) {
		this.clear();
		for (var i in scene.layers)
			this.renderLayer(scene.layers[i]);
	}

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

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