/**
 * @author Beono | http://www.beono.ru | ibeono@gmail.com
 * @version 0.7.2	 | 2009.09.28
 *
 * © License: GPLv2
 *
 */

(function($){

	var beonoGlobusIdCounter = 0;
	var obj = new Array();
	jQuery.fn.beonoGlobus = function(options) {


	var settings = {
		rotationSpeed: 100,
		framesCount: 8,
		api: false,
		css: false,
		length: 0,
		keyboardControl: true,
		mouseTurns: 2,
		debug: false,
		defaultCss :  {
			".beonoGlobus" : [{
				"border": "none",
				"margin": "0 auto"
			}],
			".beonoGlobus-frames" : [{
				"position": "relative",
				"overflow": "hidden"
			}],
			".beonoGlobus-controls" : [{
				"text-align": "center",
				"padding": "0.5em"
			}],
			".beonoGlobus-overlay" : [{
				"position": "absolute",
				"top": "0px",
				"left": "0px",
				"width": "100%",
				"height": "100%",
				"z-index" : 1000,
				"background": "red"
			}]
		}
	};

	settings = jQuery.extend(settings, options);

	this.each(function(i) {
		// Generate id for each plugin object
		id = beonoGlobusIdCounter;
		beonoGlobusIdCounter += 1;

		function beonoGlobus (linkObj, id) {


			jQuery(linkObj).find("img").hide();
			jQuery(linkObj).find("img:first-child").show();
			jQuery(linkObj).attr("id", "beonoGlobus-"+id);

			this.id = id;
			this.linkObj = linkObj;
			this.sprites = (jQuery("#beonoGlobus-"+id+" .beonoGlobus-frames img").length == 1) ? true : false;
			this.mouseTurns = settings.mouseTurns;
			this.keyboardControl = settings.keyboardControl;

			if(jQuery("#beonoGlobus-"+id+" img").length == 1) {
				this.framesCount = settings.framesCount;
			} else {
				this.framesCount = jQuery("#beonoGlobus-"+id+" img").length;
			}

			this.framesSource = false;
			this.frameWidth = 350;
			this.currentFrame = 0;
			this.currentDirection = false;
			this.rotationSpeed = settings.rotationSpeed;
			this.rotateAuto = ""
			this.rotationMode = "default";

			if (this.sprites) {
				var src = $("#beonoGlobus-"+id+" .beonoGlobus-frames img").attr("src");
				$("#beonoGlobus-"+id+" .beonoGlobus-frames img").removeAttr("src");
				jQuery("#beonoGlobus-"+id+" .beonoGlobus-frames img").hide().load(function () {
					$("#beonoGlobus-"+obj[id].id+" .beonoGlobus-frames img").show();
					obj[id].frameWidth = $("#beonoGlobus-"+obj[id].id+" .beonoGlobus-frames img").width() / obj[id].framesCount;
					$("#beonoGlobus-"+obj[id].id+" .beonoGlobus-frames").css("height", $("#beonoGlobus-"+obj[id].id+" .beonoGlobus-frames img").height() + "px");
					$("#beonoGlobus-"+id+" .beonoGlobus-frames").css("width", obj[id].frameWidth + "px");
					$("#beonoGlobus-"+obj[id].id+" .beonoGlobus-frames img").css("position", "absolute");
					$("#beonoGlobus-"+obj[id].id+" .beonoGlobus-frames img").css("width", obj[id].framesCount * obj[id].frameWidth + "px");
				}).attr("src", src);
			}

			// Events
			jQuery("#beonoGlobus-"+this.id+" .beonoGlobus-left").live("mousedown", function () {
				obj[id].rotateEvent("left");
				return false;
			});

			jQuery("#beonoGlobus-"+this.id+" .beonoGlobus-left").live("mouseout", function () {
				if (obj[id].getRotationMode() != 'auto') {
					obj[id].rotateStop();
					return false;
				}
			});

			jQuery("#beonoGlobus-"+this.id+" .beonoGlobus-right").live("mousedown", function () {
				obj[id].rotateEvent("right");
				return false;
			});

			jQuery("#beonoGlobus-"+this.id+" .beonoGlobus-right").live("mouseout", function () {
				if (obj[id].getRotationMode() != 'auto') {
					obj[id].rotateStop();
					return false;
				}
			});

			var mouseRotate = false;
			jQuery("#beonoGlobus-"+this.id+" .beonoGlobus-frames").live("mousedown", function () {
				mouseRotate = true;
				obj[id].rotateStop();
				return false;
			});

			jQuery("body").live("mouseup", function () {
				mouseRotate = false;
				obj[id].setCurrentDirection(false);
				return true;
			});

			var next_point = 0;
			var prev_left = 0;
			jQuery("#beonoGlobus-"+this.id+" .beonoGlobus-frames").live("mousemove", function (e) {

				// Если ширина очень маленька или правая кнопка мыши не была нажата
				if (jQuery(this).width() < 100 || !mouseRotate) {
					return true;
				}

				var left = e.pageX - jQuery(this).offset().left;
				//var top = e.pageY - jQuery(this).offset().top

				// Вычисляем направление
				if (left > prev_left) {
					obj[id].setCurrentDirection("right");
				} else if (left < prev_left) {
					obj[id].setCurrentDirection("left");
				}

				// Вращаем
				if (left > next_point && obj[id].getCurrentDirection() == "right" && prev_left) {
					obj[id].rotateStop();
					obj[id].rotateRight();

				} else if (left < next_point && obj[id].getCurrentDirection() == "left" && prev_left) {
					obj[id].rotateStop();
					obj[id].rotateLeft();
				}

				// Ширину всего контейнера делим на кол-во изображений,
				// таким образом определяя интервал переключений кадров
				if (left > next_point && obj[id].getCurrentDirection() == "right") {
					next_point = parseInt(left) + (jQuery(this).width() / obj[id].framesCount) / obj[id].mouseTurns;
				} else if (left < next_point && obj[id].getCurrentDirection() == "left") {
					next_point = parseInt(left) - (jQuery(this).width() / obj[id].framesCount) / obj[id].mouseTurns;
				}

				prev_left = left;

				return false;
			});

			// Обработка нажатий клавиш клавиатуры
			if(this.keyboardControl) {
				jQuery(window).keydown(function(event){
					switch (event.keyCode) {
						case 37:
							obj[id].rotateEvent("left");
						break;
						case 39:
							obj[id].rotateEvent("right");
						break;
					}
				});

				jQuery(window).keyup(function(event){
					if (event.keyCode == 37 || event.keyCode == 39) {
						for (i in obj) {
							if (obj[i].getRotationMode() == 'default') {
								obj[i].rotateStop();
							}
						}
					}
				});
			}

			// Methods
			this.debug = function (value) {
				if (settings.debug) {
					$(".debug").html(value +  "<br/>");
				}
			};

			this.applyCss = function (css) {
	    		if (css) {
					jQuery.each(css, function(selector, properties) {
						jQuery.each(properties[0], function(property, value) {
							if (jQuery.browser.msie && parseInt(jQuery.browser.version) < 7 && value == "fixed") {
								value = "absolute";
							}
							jQuery(selector).css(property, value);
						});
					});
				}
	   		};

	   		this.setRotationMode = function (value) {
	   			this.rotationMode = value;
	   		}

	   		this.getRotationMode = function () {
	   			return this.rotationMode;
	   		}

	   		this.setRotationSpeed = function (value) {
	   			this.rotationSpeed = value;
	   		}

	   		this.getRotationSpeed = function () {
	   			return this.rotationSpeed;
	   		}

	   		$("#beonoGlobus-"+this.id+" .beonoGlobus-reset").click(function () { obj[id].rotateToFrame(0);});

	   		this.rotateToFrame = function (frameNumber) {

		   		if (obj[id].currentFrame != frameNumber && frameNumber <= obj[id].framesCount) {

		   			obj[id].rotateStop();

		   			// TODO: Сделать так, чтобы крутилось в сторону где больше кадров осталось
		   			obj[id].rotateLeft();

					setTimeout(function () {
			   			obj[id].rotateToFrame(frameNumber);
			   		}, this.rotationSpeed/2);
		   		} else {
		   			obj[id].rotateStop();
		   		}

	   		}

			this.rotateLeft = function () {

				this.setCurrentDirection("left");
				// Если автопросмотр включен и setInterval ещё не был запущен
				if (this.getRotationMode() == 'auto' && !this.rotateAuto) {
					this.rotateAuto = setInterval(function () { obj[id].rotateLeft(); }, this.rotationSpeed);
				}

				if(this.sprites) {

					// Если текущий кадр последний
					if (this.currentFrame+1 >= this.framesCount) {
						this.currentFrame = -1;
					}
					this.currentFrame += 1;
					$("#beonoGlobus-"+this.id+" .beonoGlobus-frames img").css("left", "-"+this.currentFrame * this.frameWidth + "px");

				} else {

					this.currentFrame = jQuery("#beonoGlobus-"+this.id+" img").index(jQuery("#beonoGlobus-"+this.id+" img:visible"));
					jQuery("#beonoGlobus-"+this.id+" img").eq(this.currentFrame).hide();

					// Если текущий кадр последний
					if (this.currentFrame+1 >= this.framesCount) {
						this.currentFrame = -1;
					}
					this.currentFrame += 1;
					jQuery("#beonoGlobus-"+this.id+" img").eq(this.currentFrame).show();

				}
			}

			this.rotateRight = function () {

				obj[id].setCurrentDirection("right");
				// Если автопросмотр включен и setInterval ещё не был запущен
				if (this.getRotationMode() == 'auto' && !obj[id].rotateAuto) {
					this.rotateAuto = setInterval(function () { obj[id].rotateRight(); }, this.rotationSpeed);
				}

				if(this.sprites) {

					// Если текущий кадр последний
					if (this.currentFrame < 1) {
						this.currentFrame = this.framesCount;
					}
					this.currentFrame -= 1;
					$("#beonoGlobus-"+this.id+" .beonoGlobus-frames img").css("left", "-"+this.currentFrame * this.frameWidth + "px");

				} else {

					//this.debug(this.currentFrame + " " + this.framesCount);
					var index = jQuery("#beonoGlobus-"+this.id+" img").index(jQuery("#beonoGlobus-"+this.id+" img:visible"));
					jQuery("#beonoGlobus-"+this.id+" img").eq(index).hide();

					if (index < 1) {
						index = this.framesCount;
					}

					jQuery("#beonoGlobus-"+this.id+" img").eq(index-1).show();
					// Текущий кадр
					this.currentFrame = index+1;
				}
			}

			this.rotateEvent = function (direction) {

				if (obj[id].getRotationMode() == 'auto') { obj[id].rotateStop(); }

				switch (direction) {
					case "left":
						// Если уже поворачивается, то пропускаем
						if (obj[id].getCurrentDirection() == "left") { return; }
						if (obj[id].getRotationMode() == 'default') {
							obj[id].setRotationMode('auto');
							obj[id].rotateLeft();
							obj[id].setRotationMode('default');
							// TODO: Вынести отдельно
							jQuery("#beonoGlobus-"+this.id+" .beonoGlobus-left").mouseup(function () { obj[id].rotateStop(); });
						} else {
							obj[id].rotateLeft();
							// TODO: Вынести отдельно
							jQuery("#beonoGlobus-"+this.id+" .beonoGlobus-left").unbind("mouseup");
						}
						break;
					case "right":
						// Если уже поворачивается, то пропускаем
						if (obj[id].getCurrentDirection() == "right") { return; }
						if (obj[id].getRotationMode() == 'default') {
							obj[id].setRotationMode('auto');
							obj[id].rotateRight();
							obj[id].setRotationMode('default');
							// TODO: Вынести отдельно
							jQuery("#beonoGlobus-"+this.id+" .beonoGlobus-right").mouseup(function () { obj[id].rotateStop(); });
						} else {
							obj[id].rotateRight();
							// TODO: Вынести отдельно
							jQuery("#beonoGlobus-"+this.id+" .beonoGlobus-right").unbind("mouseup");
						}
						break;
				}

			}

			this.rotateStop = function () {
				if (obj[id].rotateAuto) {
					window.clearInterval(obj[id].rotateAuto);
					obj[id].rotateAuto = false;
				}
				obj[id].setCurrentDirection(false);
			}

			this.getCurrentDirection = function () {
				return obj[id].currentDirection;
			}

			this.setCurrentDirection = function (value) {
				obj[id].currentDirection = value;
			}
		}

		obj[id] = new beonoGlobus(jQuery(this), id);
		obj[id].applyCss(settings.defaultCss);


	});

	// Очищаем параметры с которыми вызван плагин
	options = false;

	if (settings.api == "last") {

		return obj[i];

	} else if(settings.api == true || settings.api == 'all') {
		var iter = 0;
		returnObj = new Array();
		for (i in obj) {
			returnObj[iter] = obj[i];
			iter++;
		}
		return returnObj;
	} else {
		return this;
	}

	};
})(jQuery);
