/**
 * @author Vlad Yakovlev (red.scorpix@gmail.com)
 * @copyright Art.Lebedev Studio (http://www.artlebedev.ru)
 * @link www.scorpix.ru
 * @version 0.1.4
 * @date 2010-03-01
 * @requires jQuery
 * @requires jCommon
 */

/**
 * Контрол для изменения размера фото.
 */
var photoSizer = (function() {

	var
		cookieName = 'photoScale',
		steps = 10,
		sealingInterval = 100;

	var
		rootEl,
		workEl,
		plusEl,
		minusEl,
		runnerEl,
		callbacks = [],
		that = {},
		isInited = false,
		scale = 0,
		width,
		dndMinLeft,
		controlState = 'isActive',
		sealingTimeoutId;

	function init() {
		if (isInited) return;

		rootEl = $('<div id="photo_size_panel"><span class="content"><span class="line"><ins class="png"></ins></span><span class="right_line"><ins class="png"></ins></span></span><span class="work_area"><span class="runner icon"><ins class="png"></ins></span></span><span class="plus icon"><ins class="png"></ins></span><span class="minus icon"><ins class="png"></ins></span></div>').appendTo($('#header'));
		workEl = rootEl.find('.work_area');
		plusEl = rootEl.find('.plus').data(controlState, false);
		minusEl = rootEl.find('.minus').data(controlState, false);
		runnerEl = rootEl.find('.runner');

		scale = getCookieValue();
		width = workEl.width();
		updateState(scale);

		$c.draggable(workEl).bind(startDnd, dnd, finishDnd);

		plusEl
			.mousedown(function() {
				$(this).hasClass('active') && step(true);
			})
			.mouseup(stopStep);
		minusEl
			.mousedown(function() {
				$(this).hasClass('active') && step(false);
			})
			.mouseup(stopStep);

		isInited = true;
	}

	function updateState(value) {
		if (1 < value) {
			value = 1;
		} else if (0 > value) {
			value = 0;
		}

		var
			oldStep = Math.round(scale * 20),
			newStep = Math.round(value * 20);

		$('body').removeClass('photo_size_' + oldStep).addClass('photo_size_' + newStep);
		scale = value;
		runnerEl.css('left', (scale * 100) + '%');
		checkControls();

		for (var i = 0; i < callbacks.length; i++) {
			callbacks[i](scale, newStep / 20);
		}
	}

	function startDnd(evt) {
		if (!$(evt.target).closest(runnerEl[0]).length) {
			updateState((parseInt(evt.pageX) - Math.round(workEl.offset().left)) / width);
		}

		dndMinLeft = parseInt(evt.pageX) - Math.round(scale * width);
		return false;
	}

	function dnd(evt) {
		updateState((parseInt(evt.pageX) - dndMinLeft) / width);
		return false;
	}

	function finishDnd(evt) {
		$c.cookie(cookieName, scale, { path: '/' });
		return false;
	}

	function step(bigger) {
		updateState(scale + (bigger ? 1 / steps : -1 / steps));
		$c.cookie(cookieName, scale, { path: '/' });

		sealingTimeoutId = setTimeout(function() {
			step(bigger);
		}, sealingInterval);
	}

	function stopStep() {
		clearTimeout(sealingTimeoutId);
	}

	function checkControls() {
		if (1 <= scale && plusEl.data(controlState)) {
			plusEl.data(controlState, false).removeClass('active');
		} else if (1 > scale && !plusEl.data(controlState)) {
			plusEl.data(controlState, true).addClass('active');
		}

		if (0 >= scale && minusEl.data(controlState)) {
			minusEl.data(controlState, false).removeClass('active');
		} else if (0 < scale && !minusEl.data(controlState)) {
			minusEl.data(controlState, true).addClass('active');
		}
	}

	function getCookieValue() {
		var value = $c.cookie(cookieName);

		if (null === value) {
			$c.cookie(cookieName, scale, { path: '/' });

			return scale;
		}

		value = parseFloat(value);

		if (0 > value || 1 < value) {
			value = 0 > value ? 0 : 1;
			$c.cookie(cookieName, value, { path: '/' });
		}

		return value;
	}

	function setScale(newScale, animate) {
		if (0 > newScale || 1 < newScale) {
			newScale = 0 > newScale ? 0 : 1;
		}

		if (newScale == scale) return;

		var oldScale = scale;

		if (animate) {
			rootEl.stop.animate({ moveX: 1 }, {
				duration: 700,
				easing: 'swing',
				step: function(t, o) {
					updateState(oldScale + (newScale - oldScale) * o.pos);
				}
			});
		} else {
			updateState(newScale);
		}
	}

	return {
		onScale: function(callback) {
			init();
			callbacks.push(callback);
		},

		getScale: function() {
			init();
			return scale;
		},

		getStep: function() {
			init();
			return Math.round(scale * 20) / 20;
		},

		setScale: function(value, animate) {
			init();
			setScale(value, animate);
		}
	};
})();
