/**
 * @author Sergey Chikuyonok (sc@design.ru)
 * @copyright Art.Lebedev Studio (http://www.artlebedev.ru)
 */

var excavator = function(){
	var canvas = document.createElement('canvas');
	var canvas_width = 450;
	var canvas_height = 400;

	canvas.width = canvas_width;
	canvas.height = canvas_height;

	var ctx = canvas.getContext('2d');
	var img = new Image();

	var to_radians = Math.PI / 180;

	/** Начальная точка, откуда рисовать экскаватор */
	var origin = {
		x: 256,
		y: 287
	};

	/** Части экскаватора */
	var parts = {
		bucket : {
			dx: 3,
			dy: 51,
			angle: -60,
			width : 72,
			height : 65,
			joint1: {
				x : 54,
				y : 44
			}
		},

		hand3 : {
			dx: 82,
			dy: 0,
			angle: -90,
			width: 19,
			height: 116,
			joint1: {
				x: 8,
				y: 108
			},
			joint2: {
				x: 3,
				y: 4
			}
		},

		hand2: {
			dx: 112,
			dy: 1,
			angle: -60,
			width: 21,
			height: 115,
			joint1: {
				x: 11,
				y: 105
			},
			joint2: {
				x: 7,
				y: 6
			}
		},
		hand1: {
			dx: 143,
			dy: 22,
			angle: 0,
			width: 32,
			height: 93,
			joint1: {
				x: 16,
				y: 92
			},

			joint2: {
				x: 16,
				y:8
			}
		},

		body: {
			dx: 186,
			dy: 3,
			angle: 0,
			width: 193,
			height: 113,
			joint2: {
				x: 64,
				y: 64
			}
		}
	}

	/**
	 * Рисует часть экскаватора
	 * @param {Object} part Часть экскаватора
	 */
	function drawPart(part){
		var dx = 0, dy = 0;
		if (part.joint1) {
			dx = -part.joint1.x;
			dy = -part.joint1.y;
		}
		ctx.drawImage(img, part.dx, part.dy, part.width, part.height, dx, dy, part.width, part.height);
	}

	/**
	 * Рисует весь экскаватор
	 */
	function draw(){
		// очищаем все
		ctx.clearRect(0, 0, canvas_width, canvas_height);

		var acc_transform = [];
		var x = 0, y = 0, a = 0;

		/**
		 * Накопление изменений матрицы трансформации для ковша
		 */
		function accumulateTransform(angle){
			acc_transform.push({x: x, y: y, r: angle});
		}

		/**
		 * Восстановление накопленных изменений матрицы трансформации для ковша
		 */
		function revertTransform(){
			for (var i = 0; i < acc_transform.length; i++) {
				var t = acc_transform[i];
				ctx.translate(t.x, t.y);
				ctx.rotate(t.r * to_radians);
			}
		}

		ctx.save();

		/*
		 * Части руки нужно нарисовать в обратном порядке, чтобы сочленения
		 * выглядели правильно. Для этого я сделаю несколько снимков
		 * матрицы трансформации, а затем, поочереди, буду восстанавливать их
		 * и рисовать нужные части руки. Ковш и тело будут рисоваться отдельно.
		 */

		// первая часть руки
		x = origin.x + parts.body.joint2.x;
		y = origin.y + parts.body.joint2.y;
		ctx.translate(x, y);
		ctx.rotate(parts.hand1.angle * to_radians);
		accumulateTransform(parts.hand1.angle);
		ctx.save();

//		drawPart(parts.hand1);

		// вторая часть руки
		x = parts.hand1.joint2.x - parts.hand1.joint1.x;
		y = parts.hand1.joint2.y - parts.hand1.joint1.y;
		ctx.translate(x, y);
		ctx.rotate(parts.hand2.angle * to_radians);
		accumulateTransform(parts.hand2.angle);
		ctx.save();


//		drawPart(parts.hand2);

		// третья часть руки
		x = parts.hand2.joint2.x - parts.hand2.joint1.x;
		y = parts.hand2.joint2.y - parts.hand2.joint1.y;
		ctx.translate(x, y);
		ctx.rotate(parts.hand3.angle * to_radians);
		accumulateTransform(parts.hand3.angle);
//		ctx.save();

		// рисуем части руки
		drawPart(parts.hand3);
		ctx.restore();
		drawPart(parts.hand2);
		ctx.restore();
		drawPart(parts.hand1);
		ctx.restore();

		// ковш
		ctx.save();
		revertTransform();
		x = parts.hand3.joint2.x - parts.hand3.joint1.x;
		y = parts.hand3.joint2.y - parts.hand3.joint1.y;
		ctx.translate(x, y);
		ctx.rotate(parts.bucket.angle * to_radians);
		drawPart(parts.bucket);
		ctx.restore();

		// рисую тело
		ctx.save();
		ctx.translate(origin.x, origin.y);
		drawPart(parts.body);
		ctx.restore();

	}

	$(function(){
		$('#excavator').append(canvas);
		img.onload = function(){
			draw();
		}
		img.src = './i/excavator.png';
	});

	var part_names = ['bucket', 'hand1', 'hand2', 'hand3'];
	var result = {};
	for (var i = 0; i < part_names.length; i++) {
		(function(/* String */ prop){
			var method_name = 'rotate' + prop.charAt(0).toUpperCase() + prop.substr(1);
			result[method_name] = function() {
				if (!arguments.length) {
					return parts[prop].angle;
				} else {
					parts[prop].angle = arguments[0];
				}
			}
		})(part_names[i]);
	}

	result.draw = draw;

	return result;

}();
