/** @package eFocus js lib */

/**
 * ScrollMenu Class
 * creates list of categories and displays scrolling productlist accordingly
 *
 * @author Rocco Janse, <rocco@efocus.nl>
 * @since 1.0, 15 jan, 2010
 * @copyright eFocus
 * @subpackage ScrollMenu
 * @uses MooTools 1.2.4.2 More, <http://www.mootools.net>
 */
var ScrollMenu = new Class({
	
	Implements: [Options],
	
	options: {
		'elCategoryPane': null,
		'elScrollingPane': null,
		'elScrollButtonUp': null,
		'elScrollButtonDown': null,
		'strDefaultCategory': null 
	},
	
	initialize: function(arrOptions) {
		
		// set config
		this.setOptions(arrOptions);
		
		// return if required containers not found
		if (!$chk(this.options.elCategoryPane) || !$chk(this.options.elScrollingPane)) {
			return false;
		}
		
		/** @var: {element} category pane element */
		this.elCategoryPane = this.options.elCategoryPane;

		/** @var: {element} category list */
		this.elCategoryList = this.elCategoryPane.getElement('ul#filtercats');
		
		/** @var: {element} category image container */
		this.elCategoryImageContainer = this.elCategoryPane.getElement('div.catimg');
		
		/** @var: {element} current product list */
		this.elProductList = null;
		
		/** @var: {element} scrolling pane element */
		this.elScrollingPane = this.options.elScrollingPane;
		
		/** @var: {string} default opened category */
		this.strDefaultCategory = this.options.strDefaultCategory;
		
		/** @var: {string} selected category */
		this.strSelectedCategory = null;
		
		/** @var: {string} selected product */
		this.strSelectedProduct = null;
		
		/** @var: {object} URI object which we use to reload categories */
		this.objUri = new URI();

		/** @var: {element} scroll button element up */
		this.elScrollButtonUp = this.options.elScrollButtonUp;
		
		/** @var: {element} scroll button element down */
		this.elScrollButtonDown = this.options.elScrollButtonDown;
		
		/** @var: {object} scroller effect object */
		this.objScrollerFx = null;

		/** @var: {object} auto scroller object */
		this.objScroller = null;

		// start functionality and create a hook to reset
		this.start();
		
	},
	
	/**
	 * start method to (re)start functionality
	 *
	 * @author Rocco Janse, <rocco@efocus.nl>
	 * @returns void
	 */		
	start: function() {

		// category and/or product selected?
		this.setSelected();

		// reset categorylist
		this.deactivateList(this.elCategoryList);

		this.initScrollFx();			
		this.initScroller();

		// activate current category
		this.activateCategory(this.strSelectedCategory);
	
		// bind events to categories
		this.bindCategoryEvents();

		// only display products if category is set
		if ($chk(this.strSelectedCategory)) {

			// bind events to products
			this.bindProductEvents();

			// show products
			this.elScrollingPane.getParent('div').setStyle('display', 'block');

			// set scrollbuttons
			this.toggleScrollButtons();

		} else {
		
			// do not show products, show teaser
			$('startteaser').setStyle('display', 'block');
		
		}
	},

	/**
	 * binds category events to listitems/links
	 *
	 * @author Rocco Janse, <rocco@efocus.nl>
	 * @returns void
	 */
	bindCategoryEvents: function() {

		this.elCategoryList.getChildren('li').each(function(elItem) {
			
			// remove old(er) events
			elItem.removeEvents();
			
			elItem.addEvents({
				'click': function(event) {
					event.stop();
					this.objUri.set('fragment', unescape(elItem.getElement('a').get('html')).trim());
					
					// write hash to url
					window.location.hash = '#'+unescape(elItem.getElement('a').get('html')).trim();

					this.start();
				}.bind(this)
			});
		}.bind(this));

	},
	
	/**
	 * binds productlist events
	 *
	 * @author Rocco Janse, <rocco@efocus.nl>
	 * @returns void
	 */
	bindProductEvents: function() {

		this.elProductList.getChildren('li').each(function(elItem) {
			
			var elClickableElement = elItem.getElement('h3');
			var strCurrentProduct = unescape(elClickableElement.get('html')).trim(); 
			
			// remove events
			elClickableElement.removeEvents();
			
			elClickableElement.addEvents({
				'mouseenter': function() {
					elItem.toggleClass('hover');
				},
				'mouseleave': function() {
					elItem.toggleClass('hover');
				},
				'click': function(event) {
					event.stop();
					this.objUri.set('fragment', this.strSelectedCategory+'-'+strCurrentProduct);
					
					// write hash to url
					window.location.hash = '#'+this.strSelectedCategory+'-'+strCurrentProduct;

					// activate product
					this.activateProduct(strCurrentProduct);
					
				}.bind(this)
			});
			
			// if current item is active; stop the scroller
			if (elItem.hasClass('active')) {
				elItem.removeEvents();
				elItem.addEvents({
					'mouseenter': function() {
						this.objScroller.stop();
					}.bind(this),
					'mouseleave': function() {
						this.objScroller.start();
					}.bind(this)
				});
			}
		}.bind(this));

	},
	
	/**
	 * sets the selected category and product
	 *
	 * @author Rocco Janse, <rocco@efocus.nl>
	 * @return void
	 */
	setSelected: function() {

		// get hash from uri
		if (window.location.hash != '') {
			
			var strUriHash = window.location.hash.replace('#', '');
			var arrRequested = strUriHash.split('-');
			
			this.strSelectedCategory = unescape(arrRequested[0]).trim();
			
			if ($defined(arrRequested[1])) {
				this.strSelectedProduct = unescape(arrRequested[1]).trim();
			} else {
				this.strSelectedProduct = '';			
			}

		}
	
	},	

	/**
	 * resets lists, removes active states
	 *
	 * @author Rocco Janse, <rocco@efocus.nl>
	 * @param {element} list element to reset
	 * @returns void
	 */		
	deactivateList: function(elList) {
		if (!$chk(elList)) {
			return false;
		}	
		
		elList.getChildren('li').each(function(elItem) {
			elItem.removeClass('active');
		});
	},

	/**
	 * activates category specified
	 *
	 * @author Rocco Janse, <rocco@efocus.nl>
	 * @param {string} category name to activate
	 * @returns void
	 */		
	activateCategory: function(strCategory) {
		
		// set current category active in category list
		this.elCategoryList.getChildren('li').each(function(elItem) {
			
			if (elItem.getElement('a').get('html') == strCategory) {
				
				// activate element
				elItem.addClass('active');
				this.objScrollerFx.toTop();
				
				// change category img
				if (elItem.getElement('img.catimg')) {
					this.elCategoryImageContainer.set('html', '');
					elItem.getElement('img.catimg').clone().inject(this.elCategoryImageContainer);
				}
			}

		}.bind(this));
		
		// set current active category to URI object
		this.objUri.set('fragment', strCategory);
			
		// also activate corresponding product, if set
		this.activateProduct(this.strSelectedProduct);

	},	
	
	/**
	 * activates product specified
	 *
	 * @author Rocco Janse, <rocco@efocus.nl>
	 * @param {string} product name to activate
	 * @returns void
	 */		
	activateProduct: function(strProduct) {
		
		// display current selected productlist
		var blnActivated = false;
		
		this.elScrollingPane.getElements('ul').each(function(elList) {
				
			if (elList.get('title') == this.strSelectedCategory) {
				
				elList.setStyle('display', 'block');
				this.elProductList = elList;
				blnActivated = true;
				
			} else {
				
				elList.setStyle('display','none');
			
			}
			
		}.bind(this));
		
		// none activated so set the first child active
		if (blnActivated == false) {
			this.elProductList = this.elScrollingPane.getFirst('ul');
			this.elProductList.setStyle('display', 'block');
		}
		
		// set current category active in category list
		if ($chk(this.elProductList)) {
			this.elProductList.getChildren('li').each(function(elItem) {
				elItem.removeClass('active');
				
				if (strProduct != null) {				
					if (elItem.getElement('h3').get('html').trim() == strProduct.trim()) {
						elItem.addClass('active');
					}
				}
			});
		}
		
		// set current active category to URI object
		this.objUri.set('fragment', this.objUri.get('fragment')+'-'+strProduct);
		
		$('startteaser').setStyle('display', 'none');
		this.elScrollingPane.setStyle('display', 'block');

	},		

	/**
	 * toggles scrollbuttons on or off, based on length of scrolling area
	 *
	 * @author Rocco Janse, <rocco@efocus.nl>
	 * @returns void
	 */
	toggleScrollButtons: function() {

		// set scroll amount to 8 items (8x30)
		var intScrollAmount = 240;

		// down button
		if (this.elProductList.getHeight() > this.elScrollingPane.getHeight()) {

			this.elScrollButtonDown.setStyle('display', 'block');

			this.elScrollButtonDown.removeEvents();
			this.elScrollButtonDown.addEvents({
				'click': function() {
					this.objScrollerFx.start(0, this.elScrollingPane.getScroll().y+intScrollAmount).chain(function() { this.start() });
					this.toggleScrollButtons.delay(100, this);
				}.bind(this)
			});

		} else {
			this.elScrollButtonDown.setStyle('display', 'none');		
		}	
	
		// up button
		if (this.elScrollingPane.getScroll().y > 0) {

			this.elScrollButtonUp.setStyle('display', 'block');

			this.elScrollButtonUp.removeEvents();
			this.elScrollButtonUp.addEvents({
				'click': function() {
					this.objScrollerFx.start(0, this.elScrollingPane.getScroll().y-intScrollAmount).chain(function() { this.start() });;
					this.toggleScrollButtons.delay(100, this);
				}.bind(this)
			});

		} else {
			this.elScrollButtonUp.setStyle('display', 'none');		
		}	
	
	},
	
	/**
	 * instanciates the scroller pane
	 *
	 * @author Rocco Janse, <rocco@efocus.nl>
	 * @returns void
	 */
	initScroller: function() {
	
		this.objScroller = new Scroller(this.elScrollingPane, {
			'area': 60,
			'velocity': 0.3,
			'fps': 25
		});
		
		this.elScrollingPane.addEvents({
			'mouseleave': function() {
				this.toggleScrollButtons();
			}.bind(this)
		});
		
		this.objScroller.start();
				
	},

	/**
	 * instanciates the scroll effect used by the scrollbuttons
	 *
	 * @author Rocco Janse, <rocco@efocus.nl>
	 * @returns void
	 */
	initScrollFx: function() {
	
		this.objScrollerFx = new Fx.Scroll(this.elScrollingPane, {
			'wheelStops': false,
			'duration': 'short',
			'link': 'ignore',
			'transition': Fx.Transitions.Expo.easeOut
		});

	}

});
