(function($) {

		var defaults = {
				auto : true,
				interval : 3500,
				counter : 0,
				continuous : false,
				rewind: false,
				debug : false,
				previous : false,
				next : false,
				nav: false,
				el : false, 
				parent : 'ul',
				children : 'li',
				width : 250,
				height : 250,
				distance : 0,
				easing: 'easeInOutQuart',
				active_class: 'on',
				per_page : 3
		}; 

		$.amplePanels = function(e, o) {
				this.options		= $.extend({}, defaults, o || {});
				this.options.el = e; 
				this.init();
		};

		$.amplePanels.fn = $.amplePanels.prototype = {

			/**
			 * constructor function
			 */
			init: function() {
				this.log('init()')
				this.setup(); 
				this.buttons(); 
			},

			/** 
			 * add styles to head, wrap container element with mask
			 */
			setup : function( ) {
				this.log('setup()'); 
				this.children = $(this.options.el).find(this.options.children); 
				switch(this.options.orientation) {
					case 'vertical': this.vertical(); break; 
					default: this.horizontal(); break; 
				}
				this.events(); 
				this.nav(); 
				this.start(); 
			},

			/**
			 * setup horizontal orientation
			 */ 
			horizontal : function() {
				this.log('horizontal()'); 
				$('<style>.ampn ' + this.options.parent + ', .ampn ' + this.options.children + ' { list-style-type:none; } .ampn ' + this.options.children + ' { float: left; margin-right: ' + this.options.distance + 'px; }</style>').appendTo('head');
				var width = (this.options.width + this.options.distance) * this.options.per_page - this.options.distance; 
				$(this.options.el).wrap($('<div class="ampn"></div>').css({ 'width': width, 'height': this.options.height, overflow: 'hidden' })); 
				this.set_width(); 
			},
			

			/**
			 * setup vertical orientation
			 */ 
			vertical : function() {
				this.log('vertical()'); 
				var width = this.options.width.slice(-1)=='%' ? this.options.width : String(parseInt(this.options.width)) + 'px'; 
				var height = String(parseInt(this.options.height)) + 'px'; 
				$('<style>.ampn ' + this.options.children + ' { width: ' + width + '; height: ' + height + '; overflow: hidden; margin-bottom: ' + this.options.distance + 'px; }</style>').appendTo('head');
				var height = (this.options.height + this.options.distance) * this.options.per_page - this.options.distance; 
				$(this.options.el).wrap($('<div class="ampn"></div>').css({ 'width': this.options.width, 'height': height, overflow: 'hidden' })); 
				this.set_height(); 
			},

			/** 
			 * add events to buttons, keys, etc.
			 */
			events: function( ) {
				var ref = this;
				this.key_down(); 
				if(this.options.previous) {
					$(this.options.previous).bind('click',function(){
						ref.stop(); 
						ref.previous(); 
					});
				}
				if(this.options.next) {
					$(this.options.next).bind('click',function(){
						ref.stop(); 
						ref.next(); 
					});
				}
			},

			nav: function( ) {
				if(this.options.nav) {
					var ref = this; 
					var nav = $('<ul></ul>');
					$.each($(this.options.el).find(this.options.children), function(i,el){
						nav.append('<li><a href="#" data-role="' + i + '">' + i + '</a></li>'); 
					});
					$(this.options.nav).append(nav); 
					$(this.options.nav).find('a').click(function(){
						ref.goto($(this).attr('data-role'));
						return false;
					})
					this.activate();
				}
			},

			/** 
			 * enable / disable navigation buttons
			 */
			buttons: function() {
				if( !this.options.continuous ) {
					$( this.options.previous ).attr('disabled', ( this.options.counter == 0 ? true : false ) ); 
					$( this.options.next ).attr('disabled', ( this.options.counter == this.last_page() ? true : false ) ); 
				}
			},

			/** 
			 * update container el's width
			 */
			set_width: function( ) {
				this.log('set_width()')
				var total = $(this.options.el).find(this.options.children).length; 
				$(this.options.el).css('width',( (this.options.width + this.options.distance) * total) ); 
			},

			/** 
			 * update container el's height
			 */
			set_height: function( ) {
				this.log('set_height()')
				var total = $(this.options.el).find(this.options.children).length; 
				$(this.options.el).css('height',( (this.options.height + this.options.distance) * total) ); 
			},

			/** 
			 * scroll to 
			 */
			goto: function( i ) {
				this.options.counter = parseInt(i); 
				this.stop(); 
				switch(this.options.orientation) {
					case 'vertical': this.slide_vertically(); break; 
					default: this.slide_horizontally(); break; 
				}
			},

			/** 
			 * next page
			 */
			next: function( ) {
				if(!this.options.rewind && this.options.counter == this.last_page()) { return false; }			
				this.count('next'); 
				switch(this.options.orientation) {
					case 'vertical': this.slide_vertically(); break; 
					default: this.slide_horizontally(); break; 
				}
				return false;
			},

			/** 
			 * previous page
			 */
			previous: function( ) {
				if(!this.options.rewind && this.options.counter == 0) { return false; }
				this.count('previous'); 
				switch(this.options.orientation) {
					case 'vertical': this.slide_vertically(); break; 
					default: this.slide_horizontally(); break; 
				}
				return false;
			},

			/** 
			 * remove active class from navigation els
			 */
			deactivate: function(  ) {
				$(this.options.nav).find('li').removeClass(this.options.active_class); 
			},

			/** 
			 * apply active class to navigation els
			 */
			activate: function(  ) {
				if(this.options.nav) {
					this.deactivate();
					var active = $(this.options.nav).find('li').get(this.options.counter); 
					$(active).addClass(this.options.active_class); 
				}
			},

			/** 
			 * increment / decrement page counter
			 */
			count: function( dir ) {
				this.dir = dir; 
				var last_page = this.last_page(); 
				switch(dir) {
					case 'previous':
						this.options.counter = this.options.counter == 0 ? parseInt(last_page) : parseInt(this.options.counter) - 1; 
						break; 
					case 'next':
						this.options.counter = this.options.counter == parseInt(last_page) ? 0 : parseInt(this.options.counter) + 1; 
						break; 
				}; 
			},

			/** 
			 * return the page counter for last page 
			 */
			last_page: function() {
				return Math.ceil ( $(this.options.el).find(this.options.children).length / this.options.per_page ) - 1; 
			},

			/** 
			 * slide panel horizontally
			 */
			slide_horizontally: function( ) {
				var left = ( this.options.width + this.options.distance ) * this.options.per_page * this.options.counter;
				var properties = { marginLeft: left * -1 + 'px' }; 
				var options = { duration: 'fast' }; 
				if(jQuery().easing) {
					options['easing'] = this.options.easing; 
				}
				if(this.rewinding()) {
					options['duration'] = 'slow'; 
				}
				$( this.options.el ).animate( properties, options );
				this.buttons(); 
				this.activate(); 
			},

			/** 
			 * slide panel vertically
			 */
			slide_vertically: function( ) {
				var top = ( this.options.height + this.options.distance ) * this.options.per_page * this.options.counter;
				var properties = { marginTop: top * -1 + 'px' }; 
				var options = { duration: 'fast' }; 
				if(jQuery().easing) {
					options['easing'] = this.options.easing; 
				}
				if(this.rewinding()) {
					options['duration'] = 200; 
				}
				$( this.options.el ).animate( properties, options );
				this.buttons(); 
				this.activate(); 
			},

			/** 
			 * on keydown event handler
			 */
			key_down: function() {
				var ref = this; 
				var previous = 37;  
				var next = 39; 
				$(document).keydown(function(e){
					switch(e.keyCode) { 
						case previous: 
							ref.stop(); 
							ref.previous(); 
							break; 
						case next: 
							ref.stop(); 
							ref.next(); 
							break; 
					}
				}); 
			},

			/** 
			 * is this animation a rewind?
			 */
			rewinding : function() {
				var rewinding = false; 
				switch(this.dir) {
					case 'next':
						rewinding = this.options.counter == 0 ? true : false; 
						break; 
					case 'previous':
						rewinding = this.options.counter == this.last_page() ? true : false; 
						break; 
				}
				return  this.options.rewind && rewinding ? true : false; 
			},

			/** 
			 * push new els onto container el
			 */
			append : function( el ) {
				this.log('append()')
				$(this.options.el).append(el); 
				this.set_width(); 
				this.buttons(); 
			},

			start : function() {
				this.log('start()'); 
				if(this.options.auto) {
					var ref = this; 
					this.interval = setInterval(function() {
						ref.next(); 
					}, this.options.interval); 
				}
			},

			stop : function() {
				this.log('stop()'); 
				clearInterval(this.interval)
			},

			/** 
			 * talk to me 
			 */
			log : function( msg ) {
				if (this.options.debug) {
					msg = typeof(msg)=='object' ? msg : 'AMPLE: '+msg; 
					!window.console ? alert(msg) : console.log(msg);
				}
			}

		}; 

		$.fn.amplePanels = function(o) {
				if (typeof o == 'string') {
						var instance = $(this).data('amplePanels'), args = Array.prototype.slice.call(arguments, 1);
						return instance[o].apply(instance, args);
				} else {
						return this.each(function() {
							$(this).data('amplePanels', new $.amplePanels(this, o));
						});
				}
		};

})(jQuery);
