var Engine = new Class({

	/* initialize needed methods
	 ======================================================================= */
	initialize: function() {
		this.globalSearchEl 	= $('hd-search-text');
		this.timeline 			= $('cell-container');
		this.graphicTimeline 	= $('graphic-timeline');
		this.growlBasket 		= $('growlbasket');
		this.popups 			= $$('.externalWindow, .flashPopupTour, .flashPopup, .blank');
		this.selfSubmits 		= $$('.singleSelect, .selfSubmit, #filter-by select');
		this.membershipType 	= $$('.membershipType');
		this.membershipTypeDesc = $$('.membershipTypeDesc');
		this.oc 				= $$('.oc');
		this.noc 				= $$('.noc');
		this.thumbLinks 		= $$('.thumbb a');
		this.parallellives 		= $$('#fhi .imageHomeContainer');
		this.radioOther			= $$('input.other');
		this.addToBasketSubmits	= $$('.addToBasket');
		this.limitedTextareas	= $$('textarea.maxlength');
		this.placeholder		= $$('.placeholder');
		// find template stuff
		this.fundRadio			= $$('#donation-method_wrapper input[type=radio]');

		this.start();
	},

	/* attach events and add the initially fired methods
	 ======================================================================= */
	start: function() {	
		this.selfSubmit();
		this.triggerDefaults();
		this.addTimelineOverlay();
		this.popupWindow();
		this.pickMembershipType();
		this.parallelLives();
		this.activateThumbs();
		this.complexNavigator();
		this.homepageNavigator();
		this.pauseVideo();
		this.otherRadio();
		this.uploadRecipient();
		this.dependentSubmit();
		this.limitTextAreas();
		this.initPlaceholder();
		this.jsHide();
		this.tabber('.tabs');
		
		if($chk(this.growlBasket)) this.growlBasket.fade('hide');
		if (this.addToBasketSubmits.length) {
			this.addToBasket(this.addToBasketSubmits);
		}
		
		// code that has to be reviewed to see if it's still needed
		this.legacy();
	},
	
	jsHide: function() {
		$$('.js_hide').setStyle('display', 'none');
	},
	
	addToBasket: function(buttons) {
		buttons.each(function(el) {
			el.addEvent('click', function() {
				var productId = this.get('rel');
				var Basket = new Shop();
				Basket.basketAction('add', productId, this.form, function() {
					this.set('disabled', 'disabled');
					var next = this.getNext()
					next.removeClass('hidden').set('href', next.get('rel')).erase('rel');
				}.bind(this));
			});
		});
	},
	
	initPlaceholder: function() {
		this.placeholder.each(function(el) {
			el.store('placeholder-text', el.get('value'));
			el.addEvents({
				'focus': function() {
					if (this.get('value') === this.retrieve('placeholder-text')) {
						this.set('value', '').removeClass('placeholder');
					}
				},
				'blur': function() {
					if (this.get('value').length === 0) {
						this.set('value', this.retrieve('placeholder-text')).addClass('placeholder');
					}
				}
			});
			// when submitting the form, ignore elements that contain their placeholder
			var form = el.getParents('form')[0];
			if (!form.retrieve('placeholder-event-added')) {
				form.addEvent('submit', function() {
					var children = form.getElements('input, textarea');
					children.each(function(ch) {
						if (ch.hasClass('placeholder')) {
							var name = ch.get('name');
							ch.erase('name');
							(function () {ch.set('name', name);}).delay(200);
						}
					});
				});
			}
			form.store('placeholder-event-added', true);
		});
	},
	
	tabber: function(selector) {
		var tabs = $$(selector);
		if (!tabs.length) return false;
		tabs.each(function(el) {
			var target = $(el.getElements('a')[0].get('rel'));
			var targets = tabs.map(function(item) {
				return $(item.getElements('a')[0].get('rel'));
			});
			el.addEvent('click', function(el, tabs, target, targets) {
				tabs.removeClass('active');
				el.addClass('active');
				targets.each(function(t) {
					t.setStyle('display', 'none');
				});
				target.setStyle('display', 'block');
			}.bind(null, [el, tabs, target, targets]));
		});
		
		tabs[0].fireEvent('click');
	},
	
	/* self-submit for the select tags
	 ======================================================================= */
	selfSubmit: function(){
		this.selfSubmits.each(function(link) {
			link.addEvent('change', function(e) {
				this.getParent('form').submit();
			});
		});
	},

	/* 
	 ======================================================================= */
	triggerDefaults: function(){
		
		// toggle focus/blur value of the global search input
		//new OverText(this.globalSearchEl);
		
		// accordion in the Subjects
		new Fx.Accordion($$('.accordionTrigger'), $$('.accordionBody'));
	},
	
	/* 
	 ======================================================================= */
	swapImage: function(el){
		// for some reason el.getParent('.image') doesn't work, so need to do it the hard way
		var imgCont = el.getParent('.info').getPrevious('.image');
		
		// fade out the image while loading a new one
		imgCont.getElement('img').fade(0.4);
		
		// insert the caption
		var caption = new Element('p', {
			html: el.get('title')
		});
		
		// insert the newly loaded image
		var image = new Asset.image(el.get('href'), {
			alt: el.get('title'),
			styles: {
				// hide it, so we can fade it in later
				opacity: 0
			},
			onload: function(){
				imgCont.empty();
				image.inject(imgCont, 'top');
				caption.inject(imgCont);
				
				// fade in the new image
				image.fade('in');
			}
		});
	},
	
	/* 
	 ======================================================================= */
	activateThumbs: function() {
		var self = this;
		this.thumbLinks.addEvent('click', function(e){
			e.stop();
			self.swapImage(this);
		});
	},
	
	/* add the timeline overlay
	 ======================================================================= */
	addTimelineOverlay: function(){
		if(this.graphicTimeline){
			
			// fetch height of the timeline
			var overlayHeight = this.graphicTimeline.getSize().y;
			
			// apply some opacity and height to the timeline overlays
			['leftOverlay', 'rightOverlay'].each(function(item, i){
				$(item).set('styles', {height: overlayHeight}).fade(0.5);
			});
			
			// same as above but for the month separators
			$$('.separator').each(function(item, i){
				item.set('styles', {height: overlayHeight + 30}).fade(0.5);
			});
		}
	},
	
	/* create some popup windows
	 ======================================================================= */
	popupWindow: function(){
		this.popups.each(function(popup, index){
			popup.addEvent('click', function(e){
				e.stop();
				var newWindow;
				
				switch(this.get('class')){
					case 'flashPopup':
						newWindow = window.open(this.get('href'), '_blank', "width=700,height=500,scrollbars=no,resizable=no,status=no,toolbar=no,location=no,menubar=no");
						break;
					case 'flashPopupTour':
						newWindow = window.open(this.get('href'), '_blank', "width=745,height=700,scrollbars=yes,resizable=yes,status=yes,toolbar=no,location=no,menubar=no");
						break;
					default:
						newWindow = window.open(this.get('href'), '_blank');
				}
				
				newWindow.focus();
			});
		});
	},
	
	/* 
	 ======================================================================= */
	parallelLives: function(){
		this.parallellives.each(function(item){
			var mc = item.getParent().getParent().getParent();
			
			// don't use try/catch - it's bad practice
			try {
				var sImage = $('rSecondImage_' + mc.get('id'));
				
				sImage.setStyle('opacity', 0);
				sImage.set('tween', {duration: 200});
				
				if(item.get('id') == 'rFirstImage'){
					if(mc.get('id') == sImage.get('rel')){
						mc.addEvents({
							mouseenter: function(){
								sImage.fade(1);
							},
							mouseleave: function(){
								sImage.fade(0);
							}	
						});
					}
				}
			} catch(e) {}
		});
	},
	
	/* toggle membership descriptions when a radio is selected
	 ======================================================================= */
	pickMembershipType: function(){
		this.membershipType.each(function(membership, i){
			
			var desc = membership.getElement('input').get('id');
			
			membership.getElements('strong').addEvent('click', function(e){
				this.membershipTypeDesc.addClass('hidden');
				$(desc + '-desc').removeClass('hidden');
			}.bind(this));
		}, this);	
	},
	
	/* 
	 ======================================================================= */
	complexNavigator: function(){
		this.complexImages = $$('#complex-image li');
		this.complexNav = $$('#complex-nav li');
		var self = this;
		
		this.complexImages.each(function(image, index){
			if (image.hasClass('active')){
				image.fade('show');
			} else {
				image.fade('hide');
			}
		});
		
		this.complexNav.each(function(nav, index){
			nav.addEvents({
				mouseenter: function(){
					// slide out all peak
					self.complexNav.getElement('span').setStyle('display', 'none');
					
					// slide in the active peak
					this.getElement('span').setStyle('display', 'block');
					
					// fade out all images
					self.complexImages.fade('out');
					
					// fade in the active image
					self.complexImages[index].fade('in');
				},
				mouseleave: function(){
					// switch back to the active season when leaving the mouse (if on the single season page)
					if (!nav.getParent('#rotator-cont').hasClass('highlightAll')){
						self.complexNav.each(function(el, i){
							if (el.hasClass('active')){
								
								// show image and the corresponding arrow
								el.getElement('span').setStyle('display', 'block');
								self.complexImages[i].fade('in');
							} else {
								
								// otherwise hide
								el.getElement('span').setStyle('display', 'none');
								self.complexImages[i].fade('out');
							}
						});
					}
				}
			});
		});
	},
	
	/* 
	 ======================================================================= */
	homepageNavigator: function(){
		var self = this;
		
		this.rotatorImages = $$('#rotator-images li');
		this.rotatorNav = $$('#rotator-nav li');
		
		this.rotatorImages.each(function(image, index){
			if (image.hasClass('active')){
				image.fade('show');
			} else {
				image.fade('hide');
			}
		});
		
		this.rotatorNav.each(function(nav, index){
			nav.addEvents({
				mouseenter: function(){
					self.rotatorNav.getElement('em').setStyle('display', 'none');
					this.getElement('em').setStyle('display', 'block');
					
					self.rotatorImages.fade('out');
					self.rotatorImages[index].fade('in');
				}
			});
		});
	},
	
	/* 
	 ======================================================================= */
	pauseVideo: function(){
		// since the .boxedMedia link will always appear in relation to a video
		// we can assume it'll have the same index
		$$('.boxedMedia').each(function(el, index){
			el.addEvents({
				click: function(){
					
					// pause video of the same index as .boxedMedia
					if ($f(index) != undefined) $f(index).pause();
				}
			});
		});
	},
	
	
	/* LEGACY: more legacy code
	 ======================================================================= */
	
	uploadRecipient: function() {
		var show = document.id('showRecipient');
		var hide = document.id('hideRecipient');
		var target = document.id('recipients-fields');
		if ($chk(show)) {
			target.set('data-original-height', target.getSize().y);
			show.addEvent('click', function(target) {
				target.morph({
					'height': target.get('data-original-height')
				});
			}.bind(this, target));
			hide.addEvent('click', function(target) {
				target.morph({
					'height': '0px'
				});
			}.bind(this, target));
		}
	},

	// Enable submit buttons only if the form has filled in stuff;
	// Something has to be selected of each radio group
	// If a checkbox contains the class required, it has to be checked (used for terms and conditions)
	dependentSubmit: function() {
		var submits = $$('.dependentSubmit');
		if (!submits.length) return false;
		submits.each(function(submit) {
			submit.set('disabled', 'disabled');
			var form = submit.getParents('form')[0];
			var radios = form.getElements('input[type=radio]');
			var checkboxes = form.getElements('input[type=checkbox].required');
			var radioGroups = radios.get('name').unique();
			radios.concat(checkboxes).each(function(el) {
				el.addEvent('click', function() {
					var target = submit,
						formValid = checkboxes.length === 0 || checkboxes.get('checked').contains(true);
					// check that each of the input groups have been selected in the form before making the target usable
					radios.each(function(el) {
						var name = el.get('name');
						var group = form.getElements('input[name=' + name + ']');
						var valid = group.get('checked').contains(true);
						if (!valid) {
							formValid = false;
						}
					});
					// I know it looks ridiculous to add, then remove a class, but if we don't then firefox can screw up if the user gets to a page via the 'back' button
					if (formValid) {
						target.addClass('disabled').removeClass('disabled').erase('disabled');
					} else {
						target.addClass('disabled').set('disabled', 'disabled');
					}
				}.bind(null, [form, radioGroups, checkboxes, submit]));
			});
		});
	},
	
	limitTextAreas: function() {
		var f = function() {
			if (this.get('value').length > 140) {
				this.set('value', this.get('value').substring(0, 140));
				return false;
			}
			return true;
		};
		this.limitedTextareas.each(function(el) {
			el.addEvents({
				'keyup': f,
				'blur': f
			});
		});
	},
	
	otherRadio: function() {
		this.radioOther.each(function(el) {
			el.set('title', el.get('value'));
			el.addEvents({
				'focus': function() {
					// remove the placeholder
					if (this.get('value') === this.get('title')) {
						this.erase('value');
					}
					var target = $pick($(this.get('rel')), this.getPrevious());
					target.set('checked', true).fireEvent('click');
				},
				'blur': function() {
					// re-add the placeholder
					if (!this.get('value')) {
						this.set('value', this.get('title'));
					}
				}
			});
		});
	},
	
	// LEGACY: more legacy code
	legacy: function() {
		
		// What's On / Event / Highlights
		$$('.hl a').each(function(el) {
			el.addEvent('click', function(e) {
				e.stop();
				
				var description = el.getParent().getParent().getElement('div');
				description.set('reveal', {duration: 300});
				
				if(el.get('rel') == 'show') {
					el.set('html', 'Close');
					el.set('rel', 'hide');
					description.reveal();
				} else {
					el.set('html', 'Open');
					el.set('rel', 'show');
					description.dissolve();
				}
			});
		});
		
		$$('.showHelp').addEvent('click', function(e) {
			$('help').toggleClass('hidden');
		});

		$$('.reset').addEvent('click', function(e) {
			window.location = $('library-search').getProperty('action');
		});	
		
		$$('.mli_overlay').each(function(el){
			el.setStyle('opacity', 0.8);
		});
		
		$$('.actionIcon').each(function(el){
			el.setStyle('opacity', 0.7);
			
			el.getParent().addEvents({
				mouseenter: function(){
					if(this.getElement('.actionIcon')) this.getElement('.actionIcon').fade(1);
				},
				
				mouseleave: function(){
					if(this.getElement('.actionIcon')) this.getElement('.actionIcon').fade(0.7);
				}
			});
		});
		
		// remove the triangle char on IE6 and lower
		$$('#navigation a, #rotator-nav span').each(function(el){
			if (Browser.Engine.trident && Browser.Engine.version <= 4){
				el.set('text', el.get('text').replace('►', ''));
			}
		});
	}
});

window.addEvents({
	load: function(){
		$$('.mli_overlay').each(function(el){
			var parentSize = el.getParent().getSize();
			el.setStyle('height', parentSize.y);
			el.setStyle('width', parentSize.x);
		});
	}
});
