(function($) {
	/**
	 * @namespace
	 */
	var BetterPlace = window.BetterPlace = {};
	BetterPlace.Abstract = {};

	//----------------------------------------
	/**
	 * For managing jQuery Collections
	 * @abstract
	 */
	BetterPlace.Abstract.Selectors = {
		/**
		 * Collection of jQuery Collections
		 * @var Object
		 */
		elements: {},

		/**
		 * Key-store of CSS selectors
		 * @var Object
		 */
		selectors: {},

		/**
		 * @param Object options
		 * @return void
		 */
		setSelectors: function(selectors) {
			$.extend(this.selectors, selectors);
		},

		/**
		 * Looks up a CSS selector by key and returns a jQuery Collection
		 * @param String key
		 * @return jQueryCollection
		 */
		getElements: function(key) {
			if (!this.selectors[key]) {
				return null;
			} else if (!this.elements[key]) {
				this.elements[key] = $(this.selectors[key]);
			}
			return this.elements[key];
		}
	};
	BetterPlace.Abstract.Selectors.$ = BetterPlace.Abstract.Selectors.getElements;

	//----------------------------------------
	/**
	 * For managing options
	 * @abstract
	 */
	BetterPlace.Abstract.Options =  {
		/**
		 * @var Object
		 */
		options: {},

		/**
		 * @param Object options
		 * @return void
		 */
		setOptions: function(options) {
			$.extend(this.options, options);
		},

		/**
		 * @param String key
		 * @param Mixed value
		 * @return void
		 */
		setOption: function(key, value) {
			this.options[key] = value;
		},

		/**
		 * @param void
		 * @return Object
		 */
		getOptions: function() {
			return this.options;
		},

		/**
		 * @param String key
		 * @param Mixed default
		 * @return Mixed
		 */
		getOption: function(key, defaultValue) {
			if (!this.options[key]  && !defaultValue) {
				return null;
			} else if (!this.options[key]  && defaultValue) {
				return defaultValue;
			}
			return this.options[key];
		}
	};
})(jQuery);

//----------------------------------------

// sandbox
(function($) {
	/**
	 * @construct
	 */
	var o = BetterPlace.Slideshow = function(el, options) {
		this.el = $(el);

		// Handle options
		var defaultOptions = {
			activeClass: 'active',
			queueClass: 'queue',
			main: 'div.main',
			notch: 'img.notch',
			items: 'li',
			activeItem: 'li.active',
			prev: 'a.prev',
			next: 'a.next',
			animateZoomIn: {left:0,width:660,height:358,top:0},
			animateZoomOut: {left:121,top:28,width:547,height:306},
			animateOffScreen: {left:-660},
			animateOnScreen: {left:0},
			animateHoverOver: {left: 125},
			animateHoverOut: {left: 115}
		};

		this.setOptions(defaultOptions);
		this.setOptions(options);

		// Handle Selectors
		var defaultSelectors = {};
		this.setSelectors(defaultSelectors);
		if (options && options.selectors) {
			this.setOptions(options.selectors);
		}

		this.loaded = {};

		this.next = $(this.getOption('next'), this.el);
		this.prev = $(this.getOption('prev'), this.el);

		//events
		this.next.
		bind('mouseover', $.proxy(_eventShowNext, this)).
		bind('mouseout', $.proxy(_eventHideNext, this)).
		bind('click', $.proxy(_eventActivateNext, this));

		if($.browser.msie) {
			this.prev.removeClass('prev-hide').bind('click', $.proxy(_eventActivatePrev, this));
		} else {
			this.prev.
			bind('mouseover', $.proxy(_eventShowPrev, this)).
			bind('mouseout', $.proxy(_eventHidePrev, this)).
			bind('click', $.proxy(_eventActivatePrev, this));
		}
	}, p = o.prototype;

	var _eventShowNext = function(e) {
		$(this.getOption('activeItem'), this.el).next().stop(true).animate(this.getOption('animateHoverOver'));
	};

	var _eventHideNext = function(e) {
		$(this.getOption('activeItem'), this.el).next().stop(true).animate(this.getOption('animateHoverOut'));
	};

	var _eventShowPrev = function(e) {
		this.prev.removeClass('prev-hide');
	};

	var _eventHidePrev = function(e) {
		this.prev.addClass('prev-hide');
	};

	var _eventActivateNext = function(e) {
		//stop default click action
		e.preventDefault();

		//temporarily stop listening to mouse out
		this.next.unbind('mouseout', _eventHideNext);

		//hide the toggles
		this.next.hide();
		this.prev.hide();

		//prepare variables that will be used for animation
		var self = this;

		var activeClass 	= this.getOption('activeClass');
		var queueClass 		= this.getOption('queueClass');

		var activeItem 		= $(this.getOption('activeItem'), this.el);

		var nextItem 		= activeItem.next();
		var nextMainImage 	= $(this.getOption('main'), nextItem);
		var nextNotchImage 	= $(this.getOption('notch'), nextItem);

		var upcomingMainImages 	= $(this.getOption('main'), nextItem.next().next()).children("img");
		var upcomingNotchImages 	= $(this.getOption('notch'), nextItem.next().next());

		//var nextSrc 		= nextFullImage.attr('src').replace('_full', '_main');

		var items 	= this.getOption('items');
		var index 	= $(items, this.el).index(nextItem);
		var size 	= $(items, this.el).size();

		var activateNext = function() {
			//- add active class to next
			//- remove queue class from next
			//- traverse to next element
			//- add queue class to the next element
			nextItem.addClass(activeClass).
				removeClass(queueClass).
			next().addClass(queueClass);

			activeItem.removeClass(activeClass);

			if(nextNotchImage.size() > 0) {
				nextMainImage.css({width: '603px'});


			}

            upcomingMainImages.add(upcomingNotchImages).each(function(i) {
                var $this = $(this);
                if (!$this.attr("src")) {
                    $this.attr("src", $this.attr("data-src"));
                }
            });



			//test to see which toggles should show
			if(index > 0) {
				self.prev.show();
			}

			if(index < (size - 1)) {
				self.next.show();
			}

			//rebind mouse out
			this.next.bind('mouseout', $.proxy(_eventHideNext, this));

		};

		//move active item to the left off the screen
		//call activateNext when done
		activeItem.animate(this.getOption('animateOffScreen'), 'slow', $.proxy(activateNext, this));
		//move the next item to the center
		var zoomIn = this.getOption('animateZoomIn');

		nextItem.stop(true).animate({left: zoomIn.left, top: zoomIn.top});

		nextMainImage.animate({width: zoomIn.width, height: zoomIn.height}).find('img').animate({width: zoomIn.width, height: zoomIn.height});

	};

	var _eventActivatePrev = function(e) {
		//stop default click action
		e.preventDefault();

		//hide the toggles
		this.next.hide();
		this.prev.hide();

		//prepare variables that will be used for animation
		var self = this;

		var activeClass = this.getOption('activeClass');
		var queueClass = this.getOption('queueClass');

		var activeItem = $(this.getOption('activeItem'), this.el);
		var activeMainImage = $(this.getOption('main'), activeItem);
		var activeNotchImage = $(this.getOption('notch'), activeItem);

		var prevItem = activeItem.prev();

		var items = this.getOption('items');
		var index = $(items, this.el).index(prevItem);
		var size = $(items, this.el).size();

		activeItem.next().removeClass(queueClass);

		activeItem.removeClass(activeClass).
			addClass(queueClass);

		var zoomOut = this.getOption('animateZoomOut');

		activeItem.animate({left: zoomOut.left, top: zoomOut.top});

		activeMainImage.
			css({width: '660px'}).
			animate({width: zoomOut.width, height: zoomOut.height}).
			find('img').
			animate({width: zoomOut.width, height: zoomOut.height});

		prevItem.addClass(activeClass).
			//attr('src', newPrevSrc).
			animate(this.getOption('animateOnScreen'), function() {
				if(index > 0) {
					self.prev.show();
				}

				if(index < (size - 1)) {
					self.next.show();
				}
			});
	};

	// Extend the prototype with some Abstract classes
	$.extend(p, BetterPlace.Abstract.Options, BetterPlace.Abstract.Selectors);

	/**
	 * Create Slideshow as a jQuery plugin
	 * var Object options
	 */
	$.fn.slideshow = function(options) {
		return this.each(function() {
		    var $this = $(this);
			if(typeof options === 'string') {
				if($this.data('slideshow') !== 'object') {
					$this.data('slideshow')[options]();
				}
			} else {
				$this.data('slideshow', new o(this, options));
			}
		});
	};
})(jQuery);

$('.slideshow-2').slideshow();
