var cacheOutput = function(func) {
	var cache = {};
	return function() {
		var args = [].splice.call(arguments, 0);
		var key = args.length+'|'+args.join('|');
		if (cache[key] === undefined)
			cache[key] = func.apply(this, arguments);
		return cache[key];
	};
};

var Evex = function(el) {
	var that = this;
	el = jQuery(el);

	var getPages = cacheOutput(function() {
		var pages = [];
		var n = 1;
		el.find('.page').each(function() {
			var page = new EvexPage(this, that, n);
			pages.push(page);
			n++;
		});
		return pages;
	});

	var initializePageLinks = cacheOutput(function() {
		var pages = getPages();
		if (pages.length > 1) {
			var topLinkContainer = getTopLinkContainer();
			for (var i = 0, ii = pages.length; i < ii; i++) {
				var element = pages[i].getTopLinkElement();
				topLinkContainer.append(element);
			}
			if (pages[0].getEvexes().length > 10) {
				var bottomLinkContainer = getBottomLinkContainer();
				if (pages.length) {
					for (var i = 0, ii = pages.length; i < ii; i++) {
						var element = pages[i].getBottomLinkElement();
						bottomLinkContainer.append(element);
					}
				}
			}
		}

		return pages;
	});

	var getPage = function(n) {
		var pages = getPages();
		for (var i = 0, ii = pages.length; i < ii; i++) {
			if (pages[i].n == n)
				return pages[i];
		}
	};

	var getTopLinkContainer = cacheOutput(function() {
		var topLinkContainer = $('<div>');
		topLinkContainer.addClass('links').addClass('top');
		topLinkContainer.insertBefore(el.find('.pages'));
		return topLinkContainer;
	});

	var getBottomLinkContainer = cacheOutput(function() {
		var topLinkContainer = $('<div>');
		topLinkContainer.addClass('links').addClass('bottom');
		topLinkContainer.insertAfter(el.find('.pages'));
		return topLinkContainer;
	});

	that.activatePage = function(n) {
		var pages = getPages();
		for (var i = 0, ii = pages.length; i < ii; i++)
			pages[i].deactivate();

		var page = getPage(n);
		if (page)
			page.activate();
	};

	var initializePages = function() {
		var pages = getPages();
		if (pages.length > 0 && pages[0].getEvexes().length === 1) {
			pages[0].getEvexes()[0].activate();
		}
	};

	var initialize = function() {
		initializePages();
		initializePageLinks();
		that.activatePage(1);
	};

	initialize();
};

var EvexCalendarPicker = function(el) {
	var that = this;
	el = jQuery(el);

	getTitleElement = cacheOutput(function() {
		var titleElement = $('<h2>');
		titleElement.addClass('title');
		titleElement.prependTo(el);
		return titleElement;
	});

	getMonths = cacheOutput(function() {
		return el.find('.month');
	});

	getPrevnextContainer = cacheOutput(function() {
		var prevnextContainer = $('<div>');
		prevnextContainer.addClass('prevnext');
		prevnextContainer.prependTo(el);

		var keys = ['prev', 'next'];
		var links = {};
		for (var i = 0; i < keys.length; i++) {
			var key = keys[i];
			var link = $('<a>');
			link.attr('href', 'javascript:');
			link.addClass(key);
			prevnextContainer.append(link);
			links[key] = link;
		}
		links['prev'].click(previous);
		links['next'].click(next);
		return prevnextContainer;
	});

	var previous = function() {
		move(-1);
	};

	var next = function() {
		move(1);
	};

	var move = function(dir) {
		var months = getMonths();
		for (var i = 0, ii = months.length; i < ii; i++) {
			if (!$(months[i]).hasClass('flash')) {
				var currentI = i;
				break;
			}
		}

		var tmpI = currentI + dir;
		if (months[tmpI]) {
			var newI = tmpI;
			for (var i = 0, ii = months.length; i < ii; i++) {
				var month = $(months[i]);
				if (i != newI) {
					month.addClass('flash');
				} else {
					month.removeClass('flash');
					var displayHtml = month.find('h3').html();
					getTitleElement().html(displayHtml);
				}
			}
		}
	};

	var initialize = function() {
		getPrevnextContainer();
		move(0);
	};

	initialize();
};

var EvexPage = function(el, whole, n) {
	var that = this;
	el = jQuery(el);
	that.n = n;

	that.getEvexes = cacheOutput(function() {
		var evexes = [];
		el.find('.evex').each(function() {
			var evex = new EvexEvex(this, that);
			evexes.push(evex);
		});
		return evexes;
	});

	that.getTopLinkElement = cacheOutput(function() {
		var element = $('<a href="javascript:">'+that.n+'</a>');
		element.click(function() {
			whole.activatePage(that.n);
		});
		return element;
	});

	that.getBottomLinkElement = cacheOutput(function() {
		var element = $('<a href="javascript:">'+that.n+'</a>');
		element.click(function() {
			$.scrollTo('.links.top', {
				duration: 500,
				onAfter: function() {
					var callback = function() {
						whole.activatePage(that.n);
					};
					setTimeout(callback, 100);
				}
			});
		});
		return element;
	});

	that.activate = function() {
		var evexes = that.getEvexes();
		for (var i = 0, ii = evexes.length; i < ii; i++)
			evexes[i].initializeLinks();
		that.getTopLinkElement().addClass('active');
		that.getBottomLinkElement().addClass('active');
		el.show();
	};

	that.deactivate = function() {
		that.getTopLinkElement().removeClass('active');
		that.getBottomLinkElement().removeClass('active');
		el.hide();
	};

	var initializeEvexes = function() {
		that.getEvexes();
	};

	var initialize = function() {
		initializeEvexes();
	};

	initialize();
};

var EvexEvex = function(el, page) {
	var that = this;
	that.el = jQuery(el);
	that.linksInitialized = false;

	getId = cacheOutput(function() {
		return that.el.attr('data-id');
	});

	that.getContentHtml = cacheOutput(function() {
		if (!that.el.hasClass('has-content-html'))
			return false;
		var contentHtml = that.el.find('.content');
		return contentHtml;
	});

	that.getLinks = cacheOutput(function() {
		var links = that.el.find('.image img');
		links = links.add(that.el.find('h3'));
		links.addClass('link');
		return links;
	});

	that.activate = function(animate) {
		if (animate)
			that.getContentHtml().slideDown(100);
		else
			that.getContentHtml().show();
	};

	that.toggle = function(animate) {
		if (animate)
			that.getContentHtml().slideToggle(100);
		else
			that.getContentHtml().toggle();
	};

	that.initializeLinks = function() {
		if (that.linksInitialized)
			return;
		var contentHtml = that.getContentHtml();
		if (contentHtml) {
			that.getLinks().click(function() {
				that.toggle();
			});
		}
		that.linksInitialized = true;
	};

	var initialize = function() {};

	initialize();
};

$(function() {
	$('.evex-list').each(function() {
		new Evex(this);
	});
	$('.evex-calendar').each(function() {
		new EvexCalendarPicker(this);
	});
});

