
Function.implement({ 
    bindWithEvent: function(bind, args){ 
        var self = this; 
        if (args != null) args = Array.from(args); 
        return function(event){ 
            return self.apply(bind, (args == null) ? arguments : [event].concat(args));
        }
    }
});

/*
	Function: buildConsoleObject
	Quick hack to prevent browsers w/o a console, or firebug from generating errors when console functions are called. Gets called immediately
*/
if (!window.console ){
    var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];
    window.console = {};
    for (var i = 0; i < names.length; ++i){ window.console[names[i]] = function() {}; }
	names = null;
}

function validateEmail( value ){
	var emailRegex = /^[a-z0-9._%-]+@[a-z0-9.-]+\.[a-z]{2,4}$/i;
	return value.test( emailRegex );				
}

Rot13 = {
	convert : function( aString ){
		return aString.replace( /[a-zA-Z]/g, function( c ){
  		return String.fromCharCode( ( c <= "Z" ? 90 : 122 ) >= ( c = c.charCodeAt(0) + 13) ? c : c - 26 );
		});
	}
};

mop = { util: {} }

mop.util.stopEvent = function( e ){
	if( e && e.stop ){
		e.stop();
	}else if( e ){
		e.returnValue = false;
	}
}

mop.util.JSONSend = function( url, data, options, method ){
	if( options ){ 
		options.url = url;
	}else{
		options = { url: url };
	}
	if( method == "POST" || !method ){
		options.method = "post";
		new Request.JSON( options ).post( data );
	}else{
		options.method = "get";
		new Request.JSON( options ).get( data );
	}
}

mop.util.getValueFromClassName = function( key, aClassName ){
	if(!aClassName) return false;
	var classNames = aClassName.split( " " );
	var result = null;
	classNames.each( function( className ){
		if( className.indexOf( key ) == 0 ) result = className.split("-")[1];
	});
	return result;
}

ovando = {};
ovando.Application = new Class({
	
	slideshows: [],
	
	initialize: function(){

//		this.parseEmailLinks();
		this.parseContactDepts();

		if( $( document.body ).get('data-backgroundimage') ) this.bgImg = new FitImage( $( document.body ).get('data-backgroundimage') );
		var slideshows = $$("div.slideshow");
		if( slideshows ) this.initSlideshows( slideshows );				
		var slidePanels = $$(".slidePanel");
		if( slidePanels ) this.initSlidePanels( slidePanels );
		var testimonials = $$("#clientTestimonialList li, #pressMentions li");
		if( testimonials ) this.resizeTestimonials( testimonials );
    if( $('nav') ) this.nav = new ovando.Nav( $("nav") );		
		if( $('aboutSection') ) this.initAbout( $('aboutSection') );
		if( $( 'contactForm' ) ) this.contactForm = new ovando.ContactForm( $( "contactForm" ) );
	},

	resizeTestimonials: function( testimonials ){
		var count = 0;
		var moduloCount = 3;
		var targetHeight = 0;
		var row = [];
		for( var i=0; i<testimonials.length; i++ ){
			var aTestimonial = testimonials[i]
			var col = ( i%moduloCount );
			var pressItem = aTestimonial.getElement( ".pressItem" );
			if( pressItem.getSize().y > targetHeight ) targetHeight = pressItem.getCoordinates().height;
			row.push( aTestimonial );
			if( col == moduloCount - 1 ){
				row.each( function( aColItem ){
					var pi = aColItem.getElement( ".pressItem" );
					pi.setStyle( 'height', targetHeight + 24 );
				});
				var row = [];
				targetHeight = 0;
			}
		};
	},

	resizeQuestions: function( questions ){
		var count = 0;
		var moduloCount = 3;
		var targetHeight = 0;
		var row = [];
		for( var i=0; i<questions.length; i++ ){
			var aQA = questions[i]
			var col = ( i%moduloCount );
			var question = aQA.getElement( "dt" );
			if( question.getSize().y > targetHeight ) targetHeight = question.getCoordinates().height;
			row.push( question );
			if( col == moduloCount - 1 || ( i == questions.length ) ){
				row.each( function( aColItem, anIndex ){
					aColItem.setStyle( 'height', targetHeight );
				});
				var row = [];
				targetHeight = 0;
			}
		};
	},
	
	initSlideshows: function( slideshows ){
		slideshows.each( function( aSlideshowElement ){
			var slideshow = new ovando.Gallery( aSlideshowElement );
		}, this );
	},

	initSlidePanels: function( slidePanels ){
		slidePanels.each( function( aSlidePanel ){
			var slidePanel = new ovando.SlidePanel( aSlidePanel );
		}, this );
	},
	
	initAbout: function( el ){
		this.initAccordion( el );
	},
	
	initAccordion: function(el){
		var headers = el.getElements('h3');
		headers.each( function( header, i ){
			if( i > 0 ){
				$( header.get('id') + "Content" ).addClass('hidden');
			}else{
				header.addClass('active');
			}
			header.addEvent('click', this.onAccordionHeaderClicked.bindWithEvent( this, [ el, header ] ) );
		}, this );
	},
	
	onAccordionHeaderClicked: function( e, parent, header ){

		if( this.activeHeader ) this.activeHeader.removeClass('active');
		this.activeHeader = header;
		this.activeHeader.toggleClass('active');

		var el = $( header.get('id') + "Content" );
		parent.getElements( '.content' ).each( function( contentItem ){
			if( contentItem != el ) contentItem.addClass('hidden');
		});
		el.toggleClass('hidden');
	},
	
	parseEmailLinks: function(){
		var emailLinks, href, text;
		emailLinks = $$(".emailLink");
//		console.log( "parseEmailLinks", emailLinks );
		emailLinks.each( function( aLink ){
			href = Rot13.convert( aLink.get("href") );
			text = Rot13.convert( aLink.get("text" ) );
//			console.log( '\t\t', aLink, "::", href, text  );
			aLink.set( "href", href );
			aLink.set( "text", text );
		});
	},
	
	parseContactDepts: function(){
		emailLinks = $$(".contactDepartment");
		emailLinks.each( function( dept ){ 
			dept.getElement('a').addEvent('click', this.openContactDept.bindWithEvent( this, dept ) );
//			console.log( 'parseContactDepts', dept );
		}, this );		
	},
	
	openContactDept: function( e, dept ){
		e.preventDefault();
//		console.log( "openContactDept", dept );
		if( dept != this.activeDept ){
			if( this.activeDept ) this.activeDept.removeClass('active');
			this.activeDept = dept;
			dept.addClass('active');
		}else{
			dept.removeClass('active');
			this.activeDept = null;	
		}
	}
	
});

ovando.Nav = new Class({

	activeNav: null,

	initialize: function( element ){
		this.element = element;
		this.topLevelChildren = this.element.getChildren( "li" );
		var activeChild = this.element.getElement( "li.active" );
		this.topLevelChildren.each( function( aChild ){
			var navItem = new ovando.NavItem( aChild, this, activeChild );
			if( activeChild == aChild ) this.activeNav = navItem;
		}, this );
	}
});

ovando.NavItem = new Class({

	element: null,
	marshal: null,
	hasChildren: false,
	showDelay: null,
	hideDelay: null,
	
	initialize: function( element, marshal, activeChild ){
		this.element = element;
		this.marshal = marshal;
		if( this.element.getElement( "ul" ) ){
			this.element.store( "Class", this );
			this.hasChildren = true;
			if( activeChild != element ) this.element.getElement( "ul" ).fade( "hide" );
			this.element.addEvent( "mouseenter", this.startShow.bindWithEvent( this ) );
			this.element.addEvent( "mouseleave", this.startHide.bindWithEvent( this ) );
		}
	},
	
	startShow: function( e ){
		mop.util.stopEvent( e );
		if( this == this.marshal.activeNav ) return;
		clearInterval( this.showDelay );
		clearInterval( this.hideDelay );
//		if( this != this.marshal.activeNav ) this.marshal.hideActiveSubNav( null );
		this.showDelay = this.showChildren.periodical( 250, this );
	},
	
	startHide: function( e ){
		mop.util.stopEvent( e );
		if( this == this.marshal.activeNav ) return;
		clearInterval( this.showDelay );
		clearInterval( this.hideDelay );
//		if( this != this.marshal.activeNav ) this.marshal.showActiveSubNav( null );
		this.hideDelay = this.hideChildren.periodical( 250, this );
	},

	hideChildren: function(){
		clearInterval( this.showDelay );
		clearInterval( this.hideDelay );
		this.element.getElement( "ul" ).fade( "out" );
	},
	
	showChildren: function(){
		clearInterval( this.showDelay );
		clearInterval( this.hideDelay );
		this.element.getElement( "ul" ).fade( "in" );		
	}

});

ovando.Gallery = new Class({
	
	element: null,
	prevLink: null,
	nextLink: null,
	imageContainer: null,
	imageIndex: 0,
	scroll: null,
	activeImage: null,
	scrollIncrement: 10,
	
	initialize: function( anElement ){
		this.element = anElement;
		this.imageContainer = anElement.getElement( ".images" );
		this.pane = anElement.getElement('.pane');
		this.images = this.imageContainer.getElements( "img.galleryImage" );
		this.prevLink = this.element.getElement( ".slideshowPrev" );
		this.nextLink = this.element.getElement( ".slideshowNext" );
		// if( this.images.length < 2 ){
		// 	this.prevLink.setStyle( "display", "none" );
		// 	this.nextLink.setStyle( "display", "none" );
		// 	return;
		// }
		var width = 0;
		this.images.each( function( anImage, anIndex ){
			width += anImage.getSize().x + parseInt( anImage.getStyle( "marginLeft" ) );
		}, this );
		this.imageContainer.setStyle( "width", width + "px" );
		this.activeImage = this.images[ this.imageIndex ];
		this.activeImage.fade( "in" );
		this.prevLink.getElement("a").set( "morph", { duration: 700 } );
		this.nextLink.getElement("a").set( "morph", { duration: 700 } );
		// this.prevLink.getElement("a").fade( .5 );
		// this.nextLink.getElement("a").fade( .5 );
		this.prevLink.addEvent( "mouseenter", this.fadeButton.bindWithEvent( this, [ this.prevLink, 'in' ] ) );
		this.nextLink.addEvent( "mouseenter", this.fadeButton.bindWithEvent( this, [ this.nextLink, 'in' ] ) );
		this.prevLink.addEvent( "mouseleave", this.fadeButton.bindWithEvent( this, [ this.prevLink, 'out' ] ) );
		this.nextLink.addEvent( "mouseleave", this.fadeButton.bindWithEvent( this, [ this.nextLink, 'out' ] ) );
		this.prevLink.addEvent( "mousedown", this.startScroll.bindWithEvent( this, -1 ) );
		this.nextLink.addEvent( "mousedown", this.startScroll.bindWithEvent( this, 1 ) );
		this.prevLink.addEvent( "mouseup", this.endScroll.bindWithEvent( this ) );
		this.nextLink.addEvent( "mouseup", this.endScroll.bindWithEvent( this ) );
		this.prevLink.addEvent( "click", this.endScroll.bindWithEvent( this ) );
		this.nextLink.addEvent( "click", this.endScroll.bindWithEvent( this ) );
		this.scroll = new Fx.Scroll( this.pane );
	},
	
	fadeButton: function( e, button, direction ){
		e.preventDefault();
		if( direction == "out" ){
			button.getElement( "a" ).morph( { "opacity": .75 } );
		}else{
			button.getElement( "a" ).morph( { "opacity": 1 } );
		}
	},
		
	previousImage: function( e ){
		mop.util.stopEvent( e );
		this.imageIndex--;
		if( this.imageIndex < 0 ) this.imageIndex = this.images.length -1 ;
 		this.activeImage = this.images[ this.imageIndex ];
		this.scroll.toElement( this.images[ this.imageIndex ] );
	},

	startScroll: function( e, dir ){
		e.preventDefault();
		clearInterval( this.scrollInterval );
		this.scrollInterval = this.scrollDiv.periodical( 30, this, dir );
	},
	
	endScroll: function( e ){
		e.preventDefault();
		clearInterval( this.scrollInterval );
	},
	
	scrollDiv: function( dir ){
		var destination = this.pane.getScroll().x + ( ( this.scrollIncrement + 1 ) * dir );
		this.scroll.set( destination, 0 );
	},
	
	nextImage: function( e ){
		mop.util.stopEvent( e );
		this.imageIndex++;
		if( this.imageIndex > this.images.length - 1 ) this.imageIndex = 0
 		this.activeImage = this.images[ this.imageIndex ];
		this.scroll.toElement( this.images[ this.imageIndex ] );
	}
	
});

ovando.SlidePanel = new Class({

	initialize: function( anElement ){
		this.element = anElement;
		this.panel = this.element.getElement( ".caption" );
		this.panelOriginalTop = this.panel.getStyle( "top" );
		this.element.addEvent( "mouseenter", this.startShow.bindWithEvent( this ) );
		this.element.addEvent( "mouseleave", this.startHide.bindWithEvent( this ) );
		this.element.addEvent( "click", this.followLink.bindWithEvent( this ) );
	},
	
	followLink: function( e ){
		mop.util.stopEvent( e );
		window.location.href = this.element.getElement( "a" ).get( "href" );
	},
	
	startShow: function( e ){
		mop.util.stopEvent( e );
		clearInterval( this.showDelay );
		clearInterval( this.hideDelay );
		this.showDelay = this.slideIn.periodical( 350, this );
	},
	
	startHide: function( e ){
		mop.util.stopEvent( e );
		clearInterval( this.showDelay );
		clearInterval( this.hideDelay );
		this.hideDelay = this.slideOut.periodical( 350, this );
		
	},
	
	slideIn: function(){
		clearInterval( this.showDelay );
		clearInterval( this.hideDelay );
		this.panel.set( "morph", { duration: 550, transition: Fx.Transitions.Quad.easeOut });
		this.panel.morph( { "top" : this.element.getSize().y - this.panel.getSize().y } );
	},
	
	slideOut: function(){
		clearInterval( this.showDelay );
		clearInterval( this.hideDelay );
		this.panel.set( "morph", { duration: 450, transition: Fx.Transitions.Quad.easeOut });
//		console.log("slideOut");
		this.panel.morph( { "top" : this.panelOriginalTop } );		
	}
	
});

ovando.ContactForm = new Class({
	
	initialize: function( anElement ){
		this.element = anElement;
		this.submitButton = this.element.getElement( ".submit" ).getElement("input");
		this.submitButton.addEvent( "click", this.submit.bindWithEvent( this ) );
	},
	
	submit: function( e, submitHref ){
		mop.util.stopEvent( e );
		var name, email, subject, message, errors, postObject, url;
		name = $( "contactName" ).get( "value" );
		email = $( "contactEmail" ).get( "value" )
		subject = $( "contactSubject" ).get( "value" )
		message = $( "contactMessage" ).get( "value" )
		errors = [];
		if( name == "" ) errors.push( "Please fill out your name." );
		if( !validateEmail( email ) ) errors.push( "Please enter a valid email." );
		if( message == "" ) errors.push( "Please fill out a message before submitting the form." );
		if( errors.length > 0 ){
			alert( "There are the following problems with your submissions:\n" + errors.join("\n") );
			return;
		}
		this.contactSpinner = new Spinner( null, { "message": "one moment please..." } );
		this.contactSpinner.show();
		postObject = {
			name: name,
			email: email,
			subject: subject,
			message: message
		};
		url = this.element.getElement( "form" ).get( "action" );
		mop.util.JSONSend( url, postObject, { onComplete: this.onContactFormSubmitted.bind( this ) });
	},
	
	onContactFormSubmitted: function( response ){
		try{
			if( !response.error ){
				this.element.set( "html", "<div class='message success'>" + response.message + "</div>" );
			}else{
				this.element.set( "html", "<div class='message error'>" + response.message + "</div>" );
			}
		}
		catch( error ){ this.element.set( "html", "<div class='message error'>" + error + "</div>" ); }
		this.contactSpinner.hide.delay( 500, this.contactSpinner );
	}	

});

window.addEvent( "domready", function(){ 
	ovando.app = new ovando.Application();
});

