(function($){
	$.fn.cards = function(options) {
		if (!this.length) return;
		
		var obj = $(this)[0];
		
		var card = $.data(obj, 'cards');
		if (card) return card;
		
		card = new $.cards(obj, options);
		$.data(obj, 'cards', card);
	};
	$.cards = function(element,options) {
		this.element = element;
		
		this.options = $.extend({
			slideOutDuration:600,
			slideInDuration:600,
			slideHoverOutDuration:400,
			slideHoverInDuration:400,
			easingOut:"easeInOutExpo",
			easingIn:"easeInOutExpo",
			easingHoverOut:"easeOutBack",
			easingHoverIn:"easeOutBack",
			initialWidth:355,
			hoverWidth:370,
			drawnWidth:740,
			autoMode_initialTimeout:0,
			autoMode_cardTimeout:3000
		}, options);
		
		this.autoMode = false;
		this.timerId = 0;
		this.firstTime = true;
		this.lastDrawn = undefined;
		
		this.init();
	};
	
	$.extend( $.cards, {
		card: function(idx) {
			if (this.items_count < 1) return undefined;
			if (idx < 0 || idx >= this.items_count) return undefined;
			return this.items[idx];
		},
		show: function(card, animate) {
			if (animate == undefined) animate = true;
			var card = card;
			var the_card = $(".the_card", card);
			if (!the_card.length) return false;
			
			$(card).addClass("animating");
			the_card = $(the_card[0]);
			if (animate) {
				the_card.stop();
				the_card.animate({width:this.options.drawnWidth+"px"}, { 
					duration: this.options.slideOutDuration, 
					queue: false, 
					easing: this.options.easingOut, 
					complete: function() {
						$(card).removeClass("animating");
					}
				});
				
			} else {
				the_card.css({width:this.options.drawnWidth+"px"});
			}
			
			this.lastDrawn = card;
			$(card).addClass("drawn");
		},
		
		hide: function(card,animate) {
			var self = this;
			var card = card;
			if (animate == undefined) animate = true;
			
			var the_card = $(".the_card", card);
			
			if (!the_card.length) return false;
			
			$(card).addClass("animating");
			the_card = $(the_card[0]);
			if (animate) {
				var w = $(card).is(".hover") ? this.options.hoverWidth : this.options.initialWidth
				the_card.stop();
				the_card.animate({width:w+"px"}, { 
					duration: this.options.slideInDuration, 
					queue: false, 
					easing: this.options.easingIn, 
					complete: function() {
						$(card).removeClass("animating");
						if ($(card).is(".hover")) {
							$.cards.hoverOn.call(self, card);
						} else {
							$.cards.hoverOff.call(self, card);
						}
					}
				});
				
			} else {
				the_card.css({width:this.options.initialWidth+"px"});
			}
			
			$(card).removeClass("drawn");
		},
		
		hoverOn: function(card, animate, stop) {
			if (animate == undefined) animate = true;
			if (stop == undefined) stop = true;
			
			var card = card;
			if ( $(card).is(".animating") || $(card).is(".drawn") ) {
				return;
			}
			
			var the_card = $(".the_card", card);
			
			if (!the_card.length) return false;
			
			the_card = $(the_card[0]);
			
			if (animate) {
				//the_card.stop();
				the_card.animate({width:this.options.hoverWidth+"px"}, { 
					duration: this.options.slideHoverOutDuration, 
					queue: false, 
					easing: this.options.easingHoverOut, 
					complete: function() {
						
					}
				});
				
			} else {
				the_card.css({width:this.options.hoverWidth+"px"});
			}
			
			$(card).addClass("hover");
		},
		
		hoverOff: function(card, animate) {
			if (animate == undefined) animate = true;
			var card = card;
			
			if ( $(card).is(".animating") || $(card).is(".drawn") ) {
				return;
			}
			var the_card = $(".the_card", card);
			
			if (!the_card.length) return false;
			
			the_card = $(the_card[0]);
			if (animate) {
				//the_card.stop();
				the_card.animate({width:this.options.initialWidth+"px"}, { 
					duration: this.options.slideHoverInDuration, 
					queue: false, 
					easing: this.options.easingHoverIn, 
					complete: function() {
					}
				});
				
			} else {
				the_card.css({width:this.options.initialWidth+"px"});
			}
			
			$(card).removeClass("hover");
		},
		
		getNext: function() {
			if (this.items_count < 1) return undefined;
			if (this.items_count == 1) return this.items[0];
			if (!this.lastDrawn) {
				return this.items[0];
			}
			cur = $(this.lastDrawn)[0];
			var next = $(cur).next(".card");
			if (next.length) {
				return next[0];
			} else {
				return this.items[0];
			}
		},
		
		getCurrent: function() {
			if (this.items_count < 1) return undefined;
			var cur = $(this.items).filter(".drawn");
			if (cur.length > 0) {
				return cur[0];
			} else {
				return undefined;
			}
		},
		
		getCurrentHover: function() {
			if (this.items_count < 1) return undefined;
			var cur = $(this.items).filter(".hover");
			if (cur.length > 0) {
				return cur[0];
			} else {
				return undefined;
			}
		},
		
		prototype: {
			init: function() {
				var self = this;
				this.cur_item = undefined;
				this.items = $("li", self.element);
				this.items_count = this.items.length;
				
				if (this.items_count > 0) {
					if ($("li.drawn", self.element).length > 0) {
						this.cur_item = $("li.drawn", self.element)[0];
						$(this.items).removeClass("drawn");
						$(this.cur_item).addClass("drawn");
					} else {
						//$("li:first", self.element).addClass("drawn");
					}
					
					$("li", self.element).not(".drawn").each(function(){
						$(".the_card", this).css({width:self.options.initialWidth+"px"});
					});
					$("li.drawn", self.element).each(function(){
						$(".the_card", this).css({width:self.options.drawnWidth+"px"});
					});
					
					
					//init event
					for(i=0; i < this.items.length; i++) {
						$(".card_drawer, .the_card", this.items[i]).bind("click", function(event){
							try {
								event.preventDefault();
								this.blur();
								$(this).blur();
							} catch(e) {
								//
							}
							
							if (self.disabled) return false;
							self.stopTimer();
							
							var card = $(this).parents(".card");
							if (card.length && !$(card).is(".drawn")) {
								var cur = self.getCurrent();
								if (cur) {
									self.hideCurrent();
								}
								$.cards.show.call(self, card[0]);
							} else {
								$.cards.hide.call(self, card[0]);
							}
							return false;
						});
						
						
						$(".card_drawer", this.items[i]).bind("mouseover", function(event){
							if (self.disabled) return false;
							self.stopTimer();
							
							var card = $(this).parents(".card");
							if (card.length) {
								$(card).addClass("hover");
								if (!$(card).is(".animating")) {
									var cur = self.getCurrentHover();
									if (cur) {
										self.hideCurrentHover();
									}
									$.cards.hoverOn.call(self, card[0]);
								}
							}
						});
						
						$(".card_drawer", this.items[i]).bind("mouseout", function(event){
							if (self.disabled) return false;
							self.stopTimer();
							
							var card = $(this).parents(".card");
							if (card.length) {
								$(card).removeClass("hover");
								if (!$(card).is(".animating")) {
									var cur = self.getCurrentHover();
									if (cur) {
										self.hideCurrentHover();
									}
									$.cards.hoverOff.call(self, card[0]);
								}
							}
						});
						
						$(this.items[i]).bind("mouseover", function(event){
							self.stopTimer();
						});
						$(this.items[i]).bind("mouseout", function(event){
							self.startTimer();
						});
						
					}
					
					this.startTimer();
					this.firstTime = false;
				}
			},

			
			startTimer: function() {
				var timeout = (this.firstTime) ? this.options.autoMode_initialTimeout : this.options.autoMode_cardTimeout;
				var self = this;
				this.stopTimer();
				this.autoMode = true;
				this.firstTime = false;
				this.timerId = window.setTimeout( function() {
					self.autoNext();
				}, timeout);
			},
			
			stopTimer: function(){ 
				if ( this.timerId > 0 ) {
					window.clearTimeout( this.timerId );
				}
				this.timeId = 0;
				this.autoMode = false;
			},
			
			showNext: function() {
				//if (!this.autoMode) return false;
				var next = this.getNext();
				if (next) {
					$.cards.show.call(this, next);
				}
			},
			
			hideCurrent: function() {
				var cur = this.getCurrent();
				if (cur) {
					$.cards.hide.call(this, cur);
				}
			},
			
			hideCurrentHover: function() {
				var cur = this.getCurrentHover();
				if (cur) {
					$.cards.hoverOff.call(this, cur);
				}
			},
			
			autoNext: function() {
				var cur = this.getCurrent();
				var next = this.getNext();
				if (cur) {
					$.cards.hide.call(this, cur);
				}
				if (cur && $(cur).is(":last-child")) {
					this.startTimer();
					return;
				}
				if (next) {
					$.cards.show.call(this, next);
				}
				this.startTimer();
			},
			
			getCurrent: function() {
				var current = $.cards.getCurrent.call(this);
				return current;
			},
			
			getNext: function() {
				var next = $.cards.getNext.call(this);
				return next;
			},
			
			getCurrentHover: function() {
				var current = $.cards.getCurrentHover.call(this);
				return current;
			},
			
			disable: function() {
				this.stopTimer();
				this.autoMode = false;
				this.firstTime = true;
				this.disabled = true;
			},
			
			enable: function() {
				this.disabled = false;
			}
		}
	});
	
	$.preloadImage = function(image, callback) {
		var self = this;
		this.file = image;
		this.callback = callback;
		this.loaded = false;
		this.aborted = false;
		this.error = false;
		this.image = new Image();
		
		this.cancelEvent = function() {
			if (this.image && this.image.onload) {
				this.image.onload = null;
			}
			if (this.image && this.image.onabort) {
				this.image.onabort = null;
			}
			if (this.image && this.image.onerror) {
				this.image.onerror = null;
			}
		};
		
		this.on_load = function() {
			self.loaded = true;
			if (self.callback && typeof self.callback == "function") {
				self.callback.apply(self, ["loaded"]);
			}
			self.cancelEvent();
		};
		
		this.on_error = function() {
			self.error = true;
			if (self.callback && typeof self.callback == "function") {
				self.callback.apply(self, ["error"]);
			}
			self.cancelEvent();
		};
		
		this.on_abort = function() {
			self.aborted = true;
			if (self.callback && typeof self.callback == "function") {
				self.callback.apply(self, ["aborted"]);
			}
			self.cancelEvent();
		};
		
		this.image.src = this.file;
		
		this.autoCheckIntervalId = 0;
		this.autoCheck = function() {
			if (self.loaded || self.aborted || self.error) {
				window.clearInterval(self.autoCheckIntervalId);
				return;
			}
			
			if (self.image && self.image.complete) {
				window.clearInterval(self.autoCheckIntervalId);
				self.loaded = true;
				if (self.callback && typeof self.callback == "function") {
					self.callback.apply(self, ["loaded"]);
				}
				self.cancelEvent();
				return;
			}
			
			if (self.image && (self.image.width || self.image.height)) {
				window.clearInterval(self.autoCheckIntervalId);
				self.loaded = true;
				if (self.callback && typeof self.callback == "function") {
					self.callback.apply(self, ["loaded"]);
				}
				self.cancelEvent();
				return;
			}
		};
		
		this.autoCheckIntervalId = window.setInterval( self.autoCheck, 500 );
	};
	
	$.preloadImages = function(images, callback) {
		if (typeof images == "string") {
			return new $.preloadImage(images, callback);
		}
		
		var self = this;
		this.images = images;
		this.callback = callback;
		this.all_complete = false;
		this.preloader = [];
		
		this.checkComplete = function() {
			if (self.preloader.length < self.images.length) return;
			if (this.all_complete) return;
			
			var all_complete = true;
			var j = 0;
			for (var i=0, n = self.preloader.length; i < n; i++) {
				if ( self.preloader[i] && self.preloader[i].loaded ) {
					j++;
				} else {
					all_complete = false;
				}
			}
			
			if (all_complete) {
				this.all_complete = true;
				if (self.callback && typeof self.callback == "function") {
					self.callback.apply(self);
				}
			}
		};
		
		for (var i=0, n = images.length; i < n; i++) {
			this.preloader[i] = new $.preloadImage(this.images[i], function(){
				self.checkComplete();
			});
		}
		
		this.autoCheckIntervalId = 0;
		this.autoCheck = function() {
			if (this.all_complete) {
				window.clearInterval(self.autoCheckIntervalId);
			}
			
			self.checkComplete();
		};
		
		this.autoCheckIntervalId = window.setInterval( self.autoCheck, 500 );
	};
	
	function preloadCardImages() {
		var baseurl = $('script[src*=javascripts/cards.js]:first').attr('src');
		baseurl = baseurl.substring(0, baseurl.indexOf("javascripts/cards.js"));
		
		var to_preload = [
			baseurl + "images/card_holder-big_saving.png",
			baseurl + "images/card_holder-experience.png",
			baseurl + "images/card_holder-simplicity.png",
			baseurl + "images/card_holder-support.png",
			baseurl + "images/card_holder-transparency.png",
			baseurl + "images/card_paper.png",
			baseurl + "images/card_arrows.gif",
			baseurl + "images/buttons.gif"
		];
		
		var preloader = new $.preloadImages(to_preload, function() {
			$("#cards .loader").hide();
			$("#cards .inner").show();
			$(".cards_list", "#cards").each(function() {
				$(this).cards({
					slideOutDuration:1600,
					slideInDuration:1200,
					easingOut:"easeInOutExpo",
					easingIn:"easeInOutExpo",
					autoMode_initialTimeout:12000,
					autoMode_cardTimeout:10000
				});
			});
		});
	}
	
	$(document).ready(function() {
		$("#cards .inner").hide();
		$("#cards .loader").show();
		
		var baseurl = $('script[src*=javascripts/cards.js]:first').attr('src');
		baseurl = baseurl.substring(0, baseurl.indexOf("javascripts/cards.js"));
		
		var loading_image = new $.preloadImage(baseurl + "images/card-ajax-loader.gif", preloadCardImages);
	});
})(jQuery);