/* 
 * British Council - Venice Biennale
 *
 * @package		BCVB
 * @author		Oskar Krawczyk (o.krawczyk@keepthinking.it)
 * @version		1.2
 * @dependecies	MooTools 1.2+
 * @copyright	Copyright (c) 2009-2010, Oskar Krawczyk (Keepthinking Ltd.)		
 * @link		http://keepthinking.it
 * 
 ======================================================================= */

Timeline.Big = new Class({
	Implements: Timeline,

	// initialize all needed methods
	initialize: function(options) {		
		this.timelineCont 	= $('timeline-big-cont');

		// check if the elements are set
		if(!$chk(this.timelineCont)) return false;
		
		this.timelineKnob 	= $('scroll-knob');
		this.timelineFilter = $('timeline-action');
		this.timelineEls 	= $('timeline-big');
		this.objectsAll 	= this.timelineEls.getChildren();
		this.objects = {
			art: 			this.timelineEls.getElements('.type_art'),
			architecture: 	this.timelineEls.getElements('.type_architecture'),
			nobiennale: 	this.timelineEls.getElements('.type_nobiennale')
		};
		
		// pre set arrays
		this.objectsHistorical 		= new Array();
		this.objectsHaveHistory 	= new Array();
		this.objectsAllHistorical 	= new Array();
		this.objectsNonHistorical 	= new Array();
		this.artHasHistory 			= new Array();
		this.architectureHasHistory = new Array();
		
		// get the filters but ommit the "Filter by" element
		this.filters 	= this.timelineFilter.getChildren().slice(0, 3);
		this.seeAll 	= this.timelineFilter.getChildren().slice(3, -1)[0];
				
		// store the type of the filter in Element Storage
		this.filters.each(function(filter) {
			filter.store('filter:type', filter.getElement('a').get('rel'));
		});
		
		new Fx.Scroll(this.timelineCont, {duration: 0}).toRight();
		
		this.presetObjects();
		this.initScroller.delay(50, this);
		this.createFilter();
	},

	/* 
	 ======================================================================= */
	presetObjects: function() {
		this.objectsHistorical = this.objectsAll.filter(function(el) {
			return (el.hasClass('type_nobiennale'));
		});	
		
		this.objectsHaveHistory = this.objectsAll.filter(function(el) {
			return (el.hasClass('hasArchive'));
		});
		
		this.objectsAllHistorical = [this.objectsHistorical, this.objectsHaveHistory].flatten();
		
		this.objectsNonHistorical = this.objectsAll.filter(function(el) {
			return !this.objectsAllHistorical.contains(el);
		}, this);
		
		this.artHasHistory = this.objectsHaveHistory.filter(function(item) {
		    return (item.get('class').split(' ')[1].slice(5) == 'art');
		});
		
		this.architectureHasHistory = this.objectsHaveHistory.filter(function(item) {
		    return (item.get('class').split(' ')[1].slice(5) == 'architecture');
		});
		
	},

	/* 
	 ======================================================================= */
	updateSmallTimeline: function() {
		// don't modify the small timeline in IE6 (it's too slow)
		if(!(Browser.Engine.trident && Browser.Engine.version == 4)) {
			this.objectsAll.each(function(el) {
				// fetch the position of elements in the wrapper
				var pos = el.getPosition($('timeline-big-wrapper')).x;
				
				// get the ID of the mini timeline element
				var miniId = $('top_timeline_'+el.get('id').slice(14));	

				var genClass = 'noHighlight_'+el.get('class').split(' ')[1].slice(5);

				// resize mini timeline elements according to the position of the elements in the big timeline
				if(pos >= -150 && pos <= 900) {
					if(el.getStyle('opacity') != 0) {
						miniId.getElement('a').morph(this.options.animateTo);
						
						miniId.removeClass(genClass);
					}
				} else {
					miniId.getElement('a').morph(this.options.animateFrom);
					
					miniId.addClass(genClass);
				}
			}, this);
		}
	},

	/* 
	 ======================================================================= */
	initScroller: function() {
		// create the custom scrollbar
		this.scroller = new MooScroller(this.timelineCont, this.timelineKnob, {
			mode: 'horizontal',
			onEnd: this.updateSmallTimeline.bind(this)
		});
		
		// enlarge the mini timeline elements
		this.scroller.fireEvent('onEnd');
	},

	/* 
	 ======================================================================= */
	newWidth: function(visibleElements) {
		// calculate the width of the wrapper
		var newWidth = visibleElements*158;
		
		// resize the wrapper
		(function() {
			this.timelineEls.setStyle('width', newWidth);
			this.scroller.update(newWidth);
		}).delay(300, this);
	},

	/* 
	 ======================================================================= */
	filterNavToggle: function(activeCount, e) {	
		// Filter toggler
		if(activeCount.length == 3) {
			this.filters.each(function(el) {
				if($(e.target) == el.getChildren()[0]) {
					el.setStyle('opacity', 1);	
				} else {
					el.setStyle('opacity', 0.3);
				}
			});
		} else {
			if($(e.target).getParent().getStyle('opacity') == 1) {
				this.filters.each(function(el) {
					el.setStyle('opacity', 1);
				});
				this.seeAll.getChildren()[0].setStyle('opacity', 1);
			} else {
				this.filters.each(function(el) {
					if($(e.target) == el.getChildren()[0]) {
						el.setStyle('opacity', 1);	
					} else {
						el.setStyle('opacity', 0.3);
					}
				});
			}
		}
	},

	/* 
	 ======================================================================= */
	createFilter: function() {
		this.seeAll.getChildren()[0].addEvent('click', function(e) {
	
			// fire when "all" was clicked
			if($(e.target) == this.seeAll.getChildren()[0]) {
				this.filters[0].getChildren()[0].fireEvent('click', [e, 'all']);
			}	
			
			// show "all" filter
			$(e.target).setStyle('opacity', 1);
		}.bind(this));
				
		// attach events to the filters
		this.filters.each(function(filter) {
			filter.set('tween', {duration: 300});
			filter = filter.getElement('a');

			filter.addEvent('click', function(e, all) {
				e.stop();
				var activeCount = this.filters.filter(function(el) {
					return (el.getStyle('opacity') == 1);
				});
				
				// check if 3 or 1 is active
				activeCount = ($chk(all) ? 3 : activeCount);
				
				this.filterNavToggle(activeCount, e);
				
				// check if "history" filter was clicked
				var isHistorical = (filter.getParent().retrieve('filter:type') == 'nobiennale');
				
				// check which filters are active
				var activeEl = this.filters.filter(function(el) {
					return (el.getStyle('opacity') == 1);
				});
				
				var temp 		= new Array();
				var toMinimize 	= new Array();
				
				// merge arrays of active types
				activeEl.each(function(el) {
					temp.push(this.objects[el.getChildren()[0].get('rel')]);
				}, this);

				// check if the historical tab is the only one which is active
				var onlyHistoricalFilter = activeEl.some(function(item){
				    return (activeEl.length == 1 && item.retrieve('filter:type') == 'nobiennale');
				});
				
				var hasHistoricalFilter = activeEl.some(function(item){
				    return (item.retrieve('filter:type') == 'nobiennale');
				});

				// this.objectsAll 				= all objects
				// this.objectsNonHistorical 	= objects that are not historical objects or don't have historical events attached
				// this.objectsHaveHistory 		= objects that have historical events attached
				// this.objectsAllHistorical 	= all historical objects
								
				if(onlyHistoricalFilter) {
					temp.push(this.objectsHaveHistory);
					
					this.objectsNonHistorical.morph({width: 0, opacity: 0});
					
					// wait a second and resize the historical events
					(function() {
						this.resizeYear('collapse', new Array());
					}).delay(1000, this);
				} else { // If user has selected History and one (but not both) of the others
					// Add the types that we're not viewing if they have history, as we need to adjust the scroll bar for them
					if(hasHistoricalFilter && activeEl.length != 3) {
						toMinimize = this.hasActiveType('art', activeEl) ? this.architectureHasHistory : this.artHasHistory;
						temp.push(toMinimize);
					}
				}
				this.objectsAll.morph({width: 0, opacity: 0});
				this.resizeYear('expand', toMinimize);
				
				// flatten merged arrays and make visible
				temp.flatten().each(function(el) {
					el.morph({width: 158, opacity: 1});
				});
				
				// set the width of the full container
				this.newWidth(temp.flatten().length);
				
				// update top timeline when changing the filter mode 
				(function() {
					this.scroller.fireEvent('onEnd');
				}).delay(500, this);
				
				// fade out the "all" filter it wasn't clicked
				if(!all && activeCount.length == 3) {
					this.seeAll.getChildren()[0].setStyle('opacity', 0.3);
				}
			}.bind(this));
		}, this);
	},

	/* check if a specified type is active in the filter menu
	 ======================================================================= */
	hasActiveType: function(type, activeEl) {
		var hasActiveType = activeEl.some(function(item){
		    return (item.retrieve('filter:type') == type);
		});
		return hasActiveType;
	},

	/* shrink and enlarge the history-related elements
	 ======================================================================= */
	resizeYear: function(mode, toMinimize) {
		if(mode == 'expand') {
			this.objectsHaveHistory.each(function(singleObject) {
				if(!this.elInArray(singleObject, toMinimize)) {
					this.morphObject(singleObject, 'expand');
				}
			}, this);
		} else {
			this.objectsHaveHistory.each(function(singleObject) {
				this.morphObject(singleObject, 'collapse');
			}, this);
		}
		
		// minimize objects that need minimizing
		toMinimize.each(function(singleObject) {
			this.morphObject(singleObject, 'collapse');
		}, this);
	},

	/* 
	 ======================================================================= */
	morphObject: function(singleObject, mode) {
		if(mode == 'expand') {
			// change the height of the main colorful area
			singleObject.getElement('.tbcMain').morph({height: 324});
			
			// change the image size
			singleObject.getElement('.tbcMain img').morph({height: 160});
			
			// show the sub title
			singleObject.getElement('.tbcMain .tbType').setStyle('display', 'block');

			// show the related attachments that are other than the historical event
			singleObject.getElements('.tbcaItem').setStyle('display', 'block');
		} else {
			// change the height of the main colorful area
			singleObject.getElement('.tbcMain').morph({height: 55});
			
			// change the image size
			singleObject.getElement('.tbcMain img').morph({height: 0});
			
			// hide the sub title
			singleObject.getElement('.tbcMain .tbType').setStyle('display', 'none');
			
			// hide the related attachments that are other than the historical event
			singleObject.getElements('.tbcaItem').setStyle('display', 'none');
		}
	},

	/* check if a specified elements is in the array
	 ======================================================================= */
	elInArray: function(el, elArray) {
		return elArray.some(function(singleObject) {
			return singleObject == el;
		});
	}
});