var Utils = {
	getFormData : function(form) {
		var params = {};
		form.find("input[type='text'], input[type='password'], input[type='hidden'], textarea, select").each(function() {
			var self = $(this);
			var key = self.attr("name");
			var value = self.val();
			params[key] = value;
		});
		form.find("input[type='checkbox'], input[type='radio']").each(function() {
			var self = $(this);
			var checked = self.attr("checked");
			var key = self.attr("name");
			if (checked) {
				var value = self.val();
				params[key] = value;
			}
		});
		return params;
	},
	
	sendForm : function(form, success, dataType) {
		if (!dataType) {
			dataType = "html";
		}
		var data = Utils.getFormData(form);
		data.ajax = true;
		var method = form.attr("method");
		var url = form.attr("action");
		$.ajax({"url": url, "type": method, "data": data, "success": success, "dataType": dataType});
	},
	
	ajaxForm : function(forms, success, dataType, func) {
		forms.each(function() {
			var form = $(this);
			form.submit(function(event) {
				event.preventDefault();
				Utils.sendForm(form, success, dataType);
				if (func) func();
			});
		});
	},
	
	liveAjaxForm : function(forms, success, dataType) {
		forms.live("submit", function() {
			var form = $(this);
			Utils.sendForm(form, success, dataType);
			return false;
		});
	},
	
	pulsate : function(el) {
		el.hide();
		var parent = el.parent();
		parent.hover(function() {
			el.fadeIn(500);
		}, function() {
			el.hide();
		});
	},
	
	counter : function(input, el, max) {
		input.keyup(function() {
			var val = input.val();
			var length = val.length;
			if (length > max) {
				input.val(val.substring(0, max));
				length = max;
			}
			el.text("(" + length + "/" + max + ")");
		}).trigger("keyup");
	},
	
	adjust : function(parent, child, animate) {
		var obj = {
			width: parent.outerWidth(),
			height: parent.outerHeight()
		};
		if (!animate) {
			child.css(obj);
		} else {
			child.animate(obj, animate);
		}
	},
	
	formatNumber : function(number, decimal) {
		number = number - 0;
		var x = number.toFixed(decimal).split('.');
		var x1 = x[0];
		var x2 = x.length > 1 ? COMMA + x[1] : '';
		var regex = /(\d+)(\d{3})/;
		while (regex.test(x1)) {
			x1 = x1.replace(regex, '$1' + DECIMAL + '$2');
		}
		return x1 + x2;
	}
};

$(document).ready(function() {
	// binds each default value to its input field
	$("input[default]").each(function() {
		var el = $(this);
		if (!el.val()) {
			el.val(el.attr("default"));
		}
	}).focus(function() {
		$(this).val("");
	}).blur(function() {
		var el = $(this);
		if(el.val().length == 0) {
			el.val(el.attr("default"));
		}
	});
	
	// bind all selects
	$("form div.select").each(function() {
		var select = new Select($(this));
	});
	
	// bind all checkboxes
	$("form div.checkbox").each(function() {
		var checkbox = new Checkbox($(this));
	});
	
	// hide each field that have hide tag
	$(".hide").hide();
	
	// remove all not visible objects from view
	$(".noscript").remove();
	
	// pulsate effect
	$(".pulsate").each(function() {
		Utils.pulsate($(this));
	});
	
	// add lightbox
	$("a[rel*='lightbox']").lightBox();
});

function Cart(forms) {
	var self = this;
	
	this._forms = forms;
	this._open = false;
	
	this._el = $("#cart");
	this._dummy = $("#cart-dummy");
	this._top = this._el.find("#cart-top");
	this._bottom = this._el.find("#cart-bottom");
	this._plants = this._bottom.find("div[article]");
	this._opener = this._top.find("#cart-opener");
	this._treeCount = this._top.find("#cart-count span");
	this._total = this._top.find("#cart-price span");
	this._openTooltip = null;
	
	this._init = function() {
		if (!self._open) {
			self._opener.removeClass("open");
			self._bottom.hide();
			self._adjust();
		}
		self._opener.click(self._toggle);
		
		this._plants.find(".trigger").each(function() {
			self._tooltip($(this));
		});
		
		Utils.ajaxForm(self._forms, self._updateCart, "json");
		Utils.liveAjaxForm($(".cart-remove"), self._updateCart, "json");
	};

	this._toggle = function() {
		self._opener.toggleClass("open");
		if (self._open) {
			self._bottom.slideUp(1000, self._adjust);
		} else {
			self._bottom.slideDown(1000, self._adjust);
		}
		self._open = !self._open;
	};
	
	this._adjust = function() {
		Utils.adjust(self._el, self._dummy);
	};
	
	this._openCart = function() {
		if (!self._open) {
			self._toggle();
		}
	};
	
	this._updateCart = function(data) {
		self._treeCount.text(data.treeCount);
		self._total.text(Utils.formatNumber(data.total, 2) + " €");
		
		var open = true;
		
		if (data.method == "remove") {
			for (var i = 0; i < 22; i++) {
				var plant = $(self._plants.get(i));
				if (plant.attr("article") == data.article.id) {
					plant.fadeOut(function() {
						self._plants = self._plants.filter("[article!='" + data.article.id + "']");
						plant.remove();
						
						var div = $("<div article='0'></div>");
						var empty = $("<img src='/gfx/reloaded/plant-empty.png' alt='empty'/>").hide();
						self._bottom.append(div.append(empty));
						self._plants.add(div);
						
						empty.fadeIn();
					});
					break;
				}
			}
		} else if (data.method == "update") {
			if (data.article.count > 0) {
				self._forms.find("input[type='text']").each(function() {
					$(this).val("");
				});
				var update = null;
				for (var i = 0; i < 22; i++) {
					var plant = $(self._plants.get(i));
					var id = plant.attr("article");
					if (id == data.article.id || id == 0) {
						update = plant;
						break;
					}
				}
				
				update.attr("article", data.article.id);
				
				var img = update.find("img")
					.attr("src", data.article.image)
					.attr("alt", data.article.tree)
					.addClass("trigger");
				
				var tooltip = self._createTooltip(img);
				tooltip.find("h2").text(data.article.tree);
				tooltip.find("input[name='id']").val(data.article.id);
				tooltip.find(".count").text(data.article.count + " Stück");
				tooltip.find(".price").text(Utils.formatNumber(data.article.price, 2) + " €");
				tooltip.find(".project").text(data.article.project);
			} else {
				open = false;
			}
		}
		
		if (open) self._openCart();
	}
	
	this._createTooltip = function(el) {
		var tooltip = 
			$("<div class='tooltip'>" +
				"<div class='clearfix' style='width: 350px;'>" +
					"<form class='cart-remove right' action='/ajax/plant/remove' method='post'>" +
						"<input type='hidden' class='hide' name='id' value=''/>" +
						"<button class='button button-cancel'><span>Pflanzung entfernen</span></button>" +
					"</form>" +
					"<h2 class='no-m'></h2>" +
				"</div>" +
				"<hr class='m-h'/>" +
				"<label>Anzahl:</label><span class='count'></span><br/>" +
				"<label>Preis:</label><span class='price'></span><br/>" +
				"<label>Projektfläche:</label><span class='project'></span>" +
			"</div>");
		
		el.after(tooltip);
		self._tooltip(el);
		
		return tooltip;
	}
	
	this._tooltip = function(el) {
		el.tooltip({
			position: "top right",
			delay: 300,
			relative: true,
			offset: [-10, -40],
			onShow : function() {
				self._openTooltip = this;
			},
			onBeforeShow : function() {
				if (self._openTooltip) self._openTooltip.hide();
			},
			onHide : function() {
				self._openTooltip = null;
			}
		});
	}
	
	this._init();
}

function AjaxPaging(id) {
	var self = this;
	
	this._id = id;
	this._el = $(id);
	this._links = null;
	this._width = this._el.width();
	this._move = this._el.innerWidth();
	this._padding = this._el.css("padding-top") + " " + this._el.css("padding-right") + " " + this._el.css("padding-bottom") + " " + this._el.css("padding-left");
	this._current = null;
	
	this._task = new Task(function() {
		var height = self._el.height();
		var outer = self._current.outerHeight();
		if (height != outer) {
			self._el.animate({ height: outer }, 500);
		}
	});
	
	this._init = function() {
		self._current = self._createNext();
		var content = self._el.children();
		self._el.css({ overflow: "hidden", padding: 0, position: "relative", width: self._el.innerWidth(), height: self._el.innerHeight() });
		self._el.append(self._current);
		self._current.append(content);
		
		self._reload();
		self._task.start(500, 1000);
	};
	
	this._reload = function() {
		self._links = self._el.find(".paging a");
		self._links.each(function() {
			var link = $(this);
			var uri = link.attr("href");
			link.click(function(event) {
				event.preventDefault();
				$.get(uri, {ajax: true}, self._callback);
			});
		});
	};
	
	this._callback = function(data) {
		var next = self._createNext();
		next.css("left", self._move).html(data);
		self._el.append(next);
		next.find("a[rel*='lightbox']").lightBox();
		
		self._current.animate({ left: -self._move }, 1000, function() {
			self._current.remove();
			self._current = next;
			self._reload();
		});
		next.animate({ left: 0 }, 1000, function() {
			self._el.animate({ height: next.outerHeight() }, 500);
		});
	};
	
	this._createNext = function() {
		var div = $("<div></div>");
		div.css({ display: "block", padding: self._padding, margin: 0, border: "0 none", width: self._width, position: "absolute", top: 0, left: 0 });
		return div;
	};
	
	this._init();
}

/**
 * Checkbox
 * 
 * Represents a checkbox, to use custom style.
 * 
 * new Checkbox(Object)
 * 
 * @param	Object	the element that represents a checkbox
 */
function Checkbox(el) {
	var self = this;
	
	this._el = el;
	this._input = this._el.find("input");
	this._input.attr("name", this._input.attr("name").replace("_", ""));
	
	this._el.click(function() {
		if (self._el.hasClass("checked")) {
			self._input.val("false");
			self._el.removeClass("checked");
		} else {
			self._input.val("true");
			self._el.addClass("checked");
		}
	});
}

/**
 * Select
 * 
 * Represents a select, to use custom style.
 * 
 * new Select(Object)
 * 
 * @param	Object	the element that represents a select
 */
function Select(el) {
	var self = this;
	
	this._el = el;
	this._button = this._el.find("button");
	this._span = this._button.find("span");
	this._list = this._el.find("ul");
	this._options = this._list.find("li");
	this._value = this._options.filter(".selected");
	this._input = this._el.find("input");
	
	this.setValue = function(option) {
		if (!option || option.length == 0) {
			option = $(self._options.get(0));
		}
		self._value.removeClass("selected");
		self._value = option;
		self._value.addClass("selected");
		self._input.val(self._value.attr("key"));
		self._span.text(self._value.text());
	}
	this.setValue(this._value);
	
	this._el.toggle(function() {
		self._list.show();
	}, function() {
		self._list.hide();
	});
	
	this._options.click(function() {
		self.setValue($(this));
		self._input.trigger("change");
	})
}

/**
 * Task
 * 
 * Represents a task, that have to run once or periodically.
 * 
 * new Task(function() { })
 * new Task({run : function() { })
 * 
 * @param	Function|Object	the element to run
 */
function Task(el, timeout, interval) {
	var self = this;
	
	this.timeout = 0;
	this.interval = 0;
	
	this._el = el;
	this._running = false;
	this._timeoutFunc = null;
	this._intervalFunc = null;
	
	/**
	 * start
	 * 
	 * Starts the task.
	 * 
	 * start()
	 * start(timeout)
	 * start(timeout, interval)
	 * 
	 * @param	Number	the timeout before first start in milliseconds
	 * @param	Number	the interval in milliseconds
	 */
	this.start = function() {
		if (!self._running) {
			if (arguments.length > 0) self.timeout = arguments[0];
			if (arguments.length > 1) self.interval = arguments[1];
			if (self.timeout <= 0) self.timeout = self.interval;

			// only run if timeout is set
			if (self.timeout > 0) {
				self._timeoutFunc = setTimeout(function() {
					// call function the first time
					self._run();
					// call function in interval, but only if interval is set
					if (self.interval > 0) {
						self._intervalFunc = setInterval(function() {
							self._run();
						}, self.interval);
					}
				}, self.timeout);
				
				self._running = true;
			}
		}
	}
	
	/**
	 * stop
	 * 
	 * Stops the task.
	 */
	this.stop = function() {
		if (self._running) {
			self.timeout = 0;
			self.interval = 0;
			clearTimeout(self._timeoutFunc);
			clearInterval(self._intervalFunc);
			self._running = false;
		}
	}
	
	/**
	 * is_running
	 * 
	 * Returns the state of the task.
	 * 
	 * @return	Boolean
	 */
	this.is_running = function() {
		return self._running;
	}
	
	/**
	 * _run
	 * 
	 * Runs the task.
	 */
	this._run = function() {
		if (self._el instanceof Function) {
			self._el();
		} else {
			self._el.run();
		}
	}
}

/**
 * TeaserManager
 */

function Teasers(first, delay, timeout) {
	var self = this;
	
	this._first = first;
	this._showing = this._first.get();
	this._delay = delay;
	this._timeout = timeout == undefined ? null : timeout;
	this._main = null;
	this._teasers = [];
	this._mainVisible = true;
	this._last = 0;
	this._task = null;
	
	this.main = function(teaser) {
		self._main = teaser;
		self._last = -1;
	}
	this.add = function(teaser) {
		self._teasers.push(teaser);
	}
	
	this._next = function() {
		if (self._countTeasers() > 1) {
			// get next
			var next;
			
			if (self._main && !self._mainVisible) {
				// main is to show
				self._mainVisible = true;
				next = self._main;
			} else {
				// main is currently visible
				self._mainVisible = false;
				next = self._teasers[self._nextId()];
			}
			// load next
			next.load(function(el) {
				// prepare next el
				var el = el;
				self._ajaxPaging(next);
				self._showing.parent().append(el);
				// hide old
				self._showing.fadeOut(500, function() {
					// justify
					self._justify(self._showing, el);
					// show new
					el.fadeIn(500, function() {
						self._showing.remove();
						self._showing = el;
					});
				});
			});
		}
	}
	
	this._ajaxPaging = function(next) {
		var el = next.get();
		el.find(".paging a").click(function(event) {
			event.preventDefault();
			var start = $(this).attr("start");
			next.load(function(el) {
				// prepare next el
				var el = el;
				self._ajaxPaging(next);
				self._showing.parent().append(el);
				// hide old
				self._showing.hide(0, function() {
					// show new
					el.show(0, function() {
						self._showing.remove();
						self._showing = el;
						self._restart();
					});
				});
			}, start);
		});
	}
	
	this._countTeasers = function() {
		var count = self._teasers.length;
		if (self.main) {
			count++;
		}
		return count;
	}
	
	this._nextId = function() {
		self._last++;
		if (self._last >= self._teasers.length) {
			self._last = 0;
		}
		return self._last;
	}
	
	this._start = function() {
		self._task.start(self._timeout, self._delay);
	}
	this._restart = function() {
		self._task.stop();
		self._start();
	}
	
	this._justify = function(last, next) {
		var parent = last.parent();
		
		if (next != undefined) {
			var lastHeight = parent.innerHeight();
			var nextHeight = next.outerHeight();
			if (nextHeight > lastHeight) {
				parent.animate({
					"height": nextHeight
				}, 500);
			}
		} else {
			parent.css("height", last.outerHeight());
		}
	}
	
	this._init = function() {
		if (self._first) {
			self._ajaxPaging(self._first);
		}
		self._task = new Task(self._next);
		self._start();
		
		// justify height of parent
		self._justify(self._showing);
	}
	
	this._init();
}

/**
 * Teaser
 */

function Teaser(url, el) {
	var self = this;
	
	this._url = url;
	this._el = el;
	this._params = {};
	
	this.load = function(callback, start) {
		// add start to params
		if (start) {
			self._params['tStart'] = start;
		}
		
		// load next
		$.get(self._url, self._params, function(data) {
			self._el = $(data).hide();
			callback(self._el);
		});
		
		// remove start from params
		delete(self._params['tStart']);
	}
	
	this.get = function() {
		return self._el;
	}
	
	this.set = function(key, value) {
		self._params[key] = value;
		return self;
	}
	
	this.copy = function() {
		return new this.constructor(self._url);
	}
	
	this.team = function(id) {
		self.set("tTeamId", id);
		return self;
	}
	this.plant = function(id) {
		self.set("tPlantId", id);
		return self;
	}
	this.user = function(id) {
		self.set("tUserId", id);
		return self;
	}
	this.type = function(type) {
		self.set("tType", type);
		return self;
	}
}

var NEWEST_USERS_TEASER = new Teaser("/teaser/users/newest");
var NEWEST_TEAMS_TEASER = new Teaser("/teaser/teams/newest");
var NEWEST_PLANTS_TEASER = new Teaser("/teaser/plants/newest");
var NEWEST_COMMENTS_TEASER = new Teaser("/teaser/comments/newest");
var BEST_USERS_TEASER = new Teaser("/teaser/users/best");
var BEST_TEAMS_TEASER = new Teaser("/teaser/teams/best");
