jQuery.extend( jQuery.easing,{easeOutSine: function (x, t, b, c, d) {
		return c * Math.sin(t/d * (Math.PI/2)) + b;
	}});
ASC = function () {
	var moduleData={},
		eventData={},
		debug=false,
		ec=0,
		createInstance = function ( moduleId ) {
			var instance = moduleData[moduleId].creator( new Sandbox() ),
				name, method;
			if( debug === true ) {
				for( name in instance ) {
					method = instance[name];
					if( typeof method == 'function' ) {
						instance[name] = function ( method, name ) {
							return function () {
								try {
									return method.apply( this, arguments );
								}
								catch( err ) {
									ASC.log( moduleId + ' - ' + name + '(): ' + err.message );
								}
							}
						}( method, name );
					}
				}
			}
			return instance;
		}
	return {
		register: function ( moduleId, creator ) {
			moduleData[moduleId] = {
				creator: creator,
				instance: null
			}
		},
		start: function ( moduleId ) {
			moduleData[moduleId].instance = createInstance( moduleId );
			moduleData[moduleId].instance.init();
		},
		stop: function ( moduleId ) {
			var data = moduleData[moduleId];
			if( data.instance ) {
				data.instance.destroy();
				data.instance = null;
			}
		},
		startAll: function () {
			var moduleId;
			for( moduleId in moduleData ) {
				if( moduleData.hasOwnProperty(moduleId) ) {
					this.start( moduleId );
				}
			}
		},
		stopAll: function () {
			var moduleId;
			for( moduleId in moduleData ) {
				if( moduleData.hasOwnProperty(moduleId) ) {
					this.stop( moduleId );
				}
			}
		},
		addListener: function ( events, handler, ctx, allowDupes ) {
			var l = events.length,
				i = 0;
			for( i; i < l; i++ ) {
				var j = 0,
					found=false,
					m;

				if( !eventData[events[i]] ) {
					eventData[events[i]] = [];
				}

				m = eventData[events[i]].length;

				for( j; j < m; j++ ) {
					if( handler == eventData[events[i]].handler && ctx == eventData[events[i]].ctx && !allowDupes ) {
						found = true;
					}
				}
				if( !found ) {
					eventData[events[i]].push({
						handler: handler,
						ctx: ctx
					});
				}
			}
		},
		dispatchEvent: function ( msgObj ) {
			var e = msgObj.e,
				data = [],
				i = 0,
				ev, l, prop;

			for( prop in msgObj.data ) {
				data.push( msgObj.data[prop] );
			}
			for( ev in eventData ) {
				if( ev == e ) {
					l = eventData[ev].length;
					for( i; i < l; i++ ) {
						var ce = eventData[ev][i];
						ce.handler.apply( ce.ctx, data );
					}
				}
			}
		},
		removeListener: function ( e, handler, ctx ) {
			var i = 0,
				l, ce;
			if( eventData[e] ) {
				l = eventData[e].length;
				for( i; i < l; i++ ) {
					ce = eventData[e][i];
					if( ce.handler == handler && ce.ctx == ctx ) {
						eventData[e].splice( i, 1 );
					}
				}
			}
		},
		clearEventType: function ( type ) {
			if( eventData[type] ) {
				eventData[type] = [];
			}
		},
		log: function ( msg ) {
			var ret, $c;
			ec++;
			ret = 'err' + ec + ': ' + msg;
			$c = $('#console');
			if( $c.length > 0 ) {
				var orig = $c.html();
				$c.html( orig + "\n" + ret );
			}
			else if( console ) {
				console.log( ret );
			}
			else {
				return ret;
			}
		}
	}
}();

Sandbox = function () {
	var href = window.location.href,
		base_url = href.match(/.+control\/\w+\//i),
		controller = href.match(/control\/\w+\/(\w+)/) ? href.match(/control\/\w+\/(\w+)/)[1] : null;

	return {
		listen: function ( events, handler, ctx, allowDupes ) {
			if( typeof events == 'string' ) {
				events = [events];
			}
			ASC.addListener( events, handler, ctx, allowDupes );
		},
		notify: function ( msgObj ) {
			ASC.dispatchEvent( msgObj );
		},
		kill: function ( e, handler, ctx ) {
			ASC.removeListener( e, handler, ctx );
		},
		killType: function ( e ) {
			ASC.clearEventType( e );
		},
		refresh: function () {
			ASC.stopAll();
			ASC.startAll();
		},
		path: function () {
			return base_url;
		},
		controller: function () {
			return controller;
		}
	}
}

ASC.register( 'resize-watch', function( sandbox ) {
	return {
		init: function () {
			$(window).bind('resize', this.resize );
		},
		resize: function ( e ) {
			sandbox.notify({
				e: 'resize-watch',
				data: {
					width: $(window).width(),
					height: $(window).height()
				}
			});
		},
		destroy: function () {
			$(window).unbind( 'resize', this.resize );
		}
	}
} );

ASC.register( 'background-adjust', function( sandbox ) {
	var backer, iw, ih, ia;
	return {
		init: function () {
			backer = $('#asc-backer').css('z-index',-1).bind('click',self.disableDrag);
			iw = backer.data('width');
			ih = backer.data('height');
			ia = iw/ih;
			sandbox.listen( 'resize-watch', this.resizing, this );
		},
		disableDrag: function ( e ) {
			e.preventDefault();
			backer.disableSelection();
		},
		resizing: function ( ww, wh ) {
			var a = ww/wh,
				s = a > ia ? ww/iw : wh/ih,
				w = iw*s,
				h = ih*s;
			
			backer.css({
				width: w,
				height: h,
				top: (wh-h)/2,
				left: (ww-w)/2
			});

			if( $('#home').length > 0 ) {
				var trg = 550 > $(window).height() ? 550 : $(window).height();
				$('.content-wrapper,body').css({
					height: trg - $('.content-wrapper').offset().top
				});
			}
		},
		destroy: function () {
			sandbox.kill( 'resize-watch', this.resizing, this );
		}
	}
} );

ASC.register( 'carousel', function ( sandbox ) {
	var self, carousel, items, navigation, currentIndex, len,
		previousItem, timer, navContainer, wrapper;
	return {
		init: function () {
			self = this;
			animating = false;

			navigation = $('.carousel-navigation-item');
			carousel = $('.carousel');
			items = carousel.find('.carousel-item');
			len = items.length;
			wrapper = $('.carousel-wrapper');
			//self.prepCarousel();

			navContainer = $('.carousel-navigation');

			navigation.bind('click', self.navClicked);

			self.setCurrentIndex( 0 );

			if( len > 1 ) {
				timer = setInterval( self.nextItem, 4500 );
			}
		},
		prepCarousel: function () {
			var buffer = items.eq(0).clone();
			wrapper.append(buffer)
			items = $('.carousel-item');
		},
		navClicked: function ( e ) {
			var obj = $(this),
				i = obj.index();
			clearTimeout( timer );
			timer = null;
			self.setCurrentIndex( i );
		},
		nextItem: function () {
			self.setCurrentIndex( currentIndex + 1 );
		},
		setCurrentIndex: function ( i ) {
			if( i == currentIndex ) {
				return false;
			}
			previousItem = items.eq(currentIndex);
			currentIndex = i;
			self.controlCurrentIndex();
			self.updateData();
		},
		controlCurrentIndex: function () {
			if( currentIndex >= len ) {
				currentIndex = 0;
			}
			else if( currentIndex < 0 ) {
				currentIndex = len-1;
			}
		},
		updateData: function ( skip ) {
			//var offset = -(items.eq(currentIndex).offset().left-wrapper.offset().left);
			navigation.eq(currentIndex).addClass('active').siblings().removeClass('active');
			/*
			wrapper.stop()[skip != true ? 'animate' : 'css']({
				marginLeft: offset
			}, 1250, 'easeOutSine', function () {
				if( currentIndex == len ) {
					currentIndex = 0;
					self.updateData(true);
				}
			});
			*/
			items.eq(0).siblings().css('opacity',0);
			items.eq(currentIndex).stop().animate({
				opacity: 1
			}, 1250).siblings().stop().animate({
				opacity: 0
			}, 1250);
		},
		destroy: function () {
			navigation.unbind('click', self.navClicked);
		}
	}
} );

ASC.register( 'map', function ( sandbox ) {
	var self, maps;
	return {
		init: function () {
			self = this;
			maps = $('.asc-map');
			maps.each( self.instantiate );
		},
		instantiate: function ( i, obj ) {
			var map = $(obj),
				latlng = new google.maps.LatLng( map.data('lat'), map.data('lng') ),
				opts = {
					zoom: 14,
					center: latlng,
					mapTypeId: google.maps.MapTypeId.ROADMAP
				},
				_map = new google.maps.Map( map[0], opts );
				if( map.data('marker') ) {
					var marker = new google.maps.Marker({
						position: latlng,
						map: _map,
						icon: map.data('marker')
					});
				}
		},
		destroy: function () {
			maps = null;
		}
	}
} );

ASC.register( 'forms', function ( sandbox ) {
	var self, form, submit, pullquote, response;

	return {
		init: function () {
			self = this;
			form = $('.asc-submit-form');
			response = form.find('.mail-response');
			submit = form.find('input[type="submit"]');
			submit.bind('click', self.submit);
		},
		submit: function ( e ) {
			e.preventDefault();
			var target = form.attr('action'),
				data = form.serialize();

			$.post( target, data, self.response );
		},
		response: function ( data ) {
			response.html( data );
		},
		destroy: function () {

		}
	}
} );

ASC.register( 'locations', function ( sandbox ) {
	var self, canvas, submit, script, geocoder, form, search, address, error, map, markers = [],
		markerCount, avgLat, avgLng, dataId, markerURL, disclaimer;

	return {
		init: function () {
			self = this;
			script = site_url + '_resources/asc2_locations/';
			disclaimer = $('.location-disclaimer');
			markerURL = public_dir+'images_sys/asc_map_marker.png';

			geocoder = new google.maps.Geocoder();
			error = $('.loc-search-error');
			form = $('.location-form');
			address = form.find('input[type="text"]');
			search = form.find('input[type="submit"]');
			address.bind({
				focus: self.clearDefault,
				blur: self.restoreDefault
			});
			self.getAllSchools();
			search.bind('click', self.search);
		},
		clearDefault: function ( e ) {
			if( address.val() == 'Address' ) {
				address.val('');
			}
		},
		restoreDefault: function ( e ) {
			if( address.val() == '' || address.val == ' ' ) {
				address.val('Address');
			}
		},
		getAllSchools: function () {
			$.ajax({
				type: 'post',
				url: script+'&f=show_schools',
				dataType: 'json',
				success: self.showReturn
			});
		},
		showReturn: function ( data ) {
			var i, pos, opts, center, c=0;
			opts = {
					zoom: 12,
					mapTypeId: google.maps.MapTypeId.ROADMAP,
					center: new google.maps.LatLng( 0,0 )
			};
			var el = document.getElementById('locations_map'),
				dataId = $(el).data('id');
			
			map = new google.maps.Map(document.getElementById('locations_map'), opts );
			var latlngbounds = new google.maps.LatLngBounds();
			for( i in data ) {
				if( ( dataId == 0 ) || ( data[i].id == dataId ) ) {

					pos = new google.maps.LatLng(data[i].lat,data[i].lng);
					var size = new google.maps.Size(36,35),
						origin = new google.maps.Point(0,0),
						anchor = new google.maps.Point(9,33),
						image = new google.maps.MarkerImage( markerURL, size, origin, anchor ),
						content = '<div id="info-content"><a href="'+data[i].url+'">'+data[i].name+'</a>\n<div>'+data[i].address+'</div></div>',
						infowindow = new google.maps.InfoWindow({
							content: content
						}),
						marker = new google.maps.Marker({
							position: pos,
							map: map,
							title: data[i].name,
							icon: image
						});
					markers.push( marker );
					self.bindLink( marker, c, infowindow );
					latlngbounds.extend( pos );
					c++;
				}
			};
			markerCount = markers.length;
			//c = 4;
			map.setCenter( latlngbounds.getCenter() );
			if( c > 1 ) { 
				 map.fitBounds( latlngbounds );
			}
			else {
				map.setZoom(14);
			}
		},
		bindLink: function ( marker,c,infowindow ) {
			google.maps.event.addListener( marker, 'click', function () {
				infowindow.open( map, marker );
			} );
		},
		search: function ( e ) {
			e.preventDefault();
			disclaimer.hide();
			error.html('');
			var addr = address.val();
			geocoder.geocode({'address':addr}, function( results, status ) {
				if( status == google.maps.GeocoderStatus.OK ) {
					var latlng = [];
					for( var i in results[0].geometry.location ) {
						latlng.push( results[0].geometry.location[i] );
					}
					var target = script+'&f=search',
						data = {
							lat: latlng[0],
							lng: latlng[1]
						}
					$.post( target, data, self.updateSearch, 'json' );
				} else {
					$('.search-response').remove();
					error.html('Sorry, we were unable to find the address that you have supplied.');
				}
			} );
		},
		updateSearch: function ( data ) {
			disclaimer.show();
			var home = new google.maps.LatLng( data.center[0], data.center[1] ),
				response, header, item, center;

			if( markers.length > markerCount ) {
				markers[markers.length-1].setMap(null);
				markers.splice(markers.length-1,1);
			}

			var marker = new google.maps.Marker({
				position: home,
				map: map,
				title: 'You'
			});

			markers.push( marker );

			$('.search-response').remove();
			response = $('<div class="search-response"></div>');
			header = '<ul class="loc-row header clearfix">\n';
			header += '\t<li class="loc-place">New York Ascend Schools</li>\n';
			header += '\t<li class="loc-district">District</li>\n';
			header += '\t<li class="loc-city">City</li>\n';
			header += '\t<li class="loc-dist">Distance*</li>\n';
			header += '</ul>\n';
			header = $(header);
			response.append(header);
			for( var i in data.schools ) {
				item = '<ul class="loc-row clearfix">\n';
				item += '\t<li class="loc-place">'+data.schools[i].name+'</li>\n';
				item += '\t<li class="loc-district">'+data.schools[i].district+'</li>\n';
				item += '\t<li class="loc-city">'+data.schools[i].city+'</li>\n';
				item += '\t<li class="loc-dist">'+data.schools[i].distance+'</li>\n';
				item += '</ul>\n';
				item = $(item);
				response.append(item);
			}
			form.after(response);

			var latlngbounds = new google.maps.LatLngBounds();
			for( var i in markers ) {
				latlngbounds.extend( markers[i].position );
			}
			map.setCenter( latlngbounds.getCenter() );
			map.fitBounds( latlngbounds );
		},
		destroy: function () {

		}
	}
} );

ASC.register( 'search', function ( sandbox ) {
	var self, searches;
	return {
		init: function () {
			self = this;
			searches = $('input[name="query"]');
			searches.bind({
				focus: self.focus,
				blur: self.blur
			});
		},
		focus: function ( e ) {
			var field = $(this);
			if( field.val().toLowerCase() == 'search' ) {
				field.val('');
			}
		},
		blur: function ( e ) {
			var field = $(this);
			if( field.val() == '' ) {
				field.val('Search');
			}
		},
		destroy: function () {

		}
	}
} );

ASC.register( 'sidebar-adjust', function ( sandbox ) {
	var sidebar, self, footer, content;
	return {
		init: function () {

			self = this;
			sidebar = $('.left-nav').outerHeight() + parseInt( $('.left-nav').css('margin-top') );
			content = $('.body').height();
			footer = $('.footer');
			if( content < sidebar ) {
				var diff = sidebar - content;
				footer.css('padding-top', diff + 48);
			}
		},
		destroy: function () {
			
		}
	}
} );

ASC.register( 'home-carousel', function ( sandbox ) {
	var self, wrapper, carousel, items, timer, currentIndex, l, oldIndex, dots, msie;
	return {
		init: function () {
			self = this;
			currentIndex=0;
			msie = $.browser.msie==true && $.browser.version < 9 ? true : false;
			wrapper = $('.bg-carousel-wrapper');
			carousel = wrapper.find('.bg-carousel');
			dots = $('.carousel-sprite').bind('click',self.dotClicked);
			$('.cheech-right-full, .cheech-left-full').css('opacity',.4);
			items = carousel.find('.bg-item');
			l = items.length;
			sandbox.listen('resize-watch',self.adjust,self);
			timer = setInterval( self.advance, 5500 );
			$(window).bind('keydown', self.routeKeys);
			sandbox.notify({
				e: 'resize-watch',
				data: {
					w: $(window).width(),
					h: $(window).height()
				}
			});
		},
		routeKeys: function ( e ) {
			switch( e.keyCode ) {
				case 37:
					clearInterval( timer );
					e.preventDefault();
					self.regress();
					break;
				case 39:
					clearInterval( timer );
					e.preventDefault();
					self.advance();
					break;
			}
		},
		dotClicked: function ( e ) {
			e.preventDefault();
			clearInterval( timer );
			var index = $(this).data('index');
			self.setCurrentIndex( index );
		},
		advance: function () {
			self.setCurrentIndex(currentIndex+1);
		},
		regress: function () {
			self.setCurrentIndex(currentIndex-1);
		},
		setCurrentIndex: function ( index ) {
			if( currentIndex == index ) return false;
			oldIndex = currentIndex;
			currentIndex = index;
			self.controlCurrentIndex();
			self.updateData();
		},
		controlCurrentIndex: function () {
			if( currentIndex >= l ) {
				currentIndex = 0;
			}
			else if ( currentIndex < 0 ) {
				currentIndex = l-1;
			}
		},
		updateData: function () {
			dots.eq(currentIndex).addClass('active').siblings().removeClass('active');

			time = msie == false ? 750 : null;

			items.eq(oldIndex)[msie==true ? 'hide' : 'fadeOut'](time);
			items.eq(currentIndex)[msie==true ? 'show' : 'fadeIn'](time);

		},
		adjust: function ( w, h ) {
			wrapper.css({
				left: (w-866)/2
			});
			dots.parent('nav').stop().animate({
				right: (w-833)/2 > 10 ? (w-833)/2 : 10
			});
			items.each( function () {
				var o = $(this);
				self.adjustCell( w, h, o );
			} );
		},
		adjustCell: function ( w, h, o ) {
			var img = o.find('img'),
				iw = img.data('width'),
				ih = img.data('height'),
				a = w/h,
				ia = iw/ih,
				s = a>ia ? w/iw : h/ih,
				nw = iw*s,
				nh = ih*s,
				l = (w-nw)/2,
				t = (h-nh)/2,
				caption = o.find('.slide-caption'),
				side = caption.hasClass('right') ? 'right' : 'left',
				cheech, cheechExtend;

			img.css({
				width: nw,
				height: nh,
				marginLeft: l,
				marginTop: t
			});

			var dist = (w-caption.width())/2-433 + caption.width()/2;
			dist = dist > 0 ? dist : 0;
			if( side == 'right' ) {
				caption.stop().animate({
					right: dist
				});
				var cheech = o.find('.cheech-right'),
					cheechExtend = o.find('.cheech-right-full');

				cheech.css({
					right: dist
				});
				cheechExtend.css({
					width: dist
				});
			}
			else {
				caption.stop().animate({
					left: dist
				});

				var cheech = o.find('.cheech-left'),
					cheechExtend = o.find('.cheech-left-full').css('opacity',.4);

				cheech.css({
					left: dist
				});
				cheechExtend.css({
					width: dist
				});
			}
		},
		destroy: function () {}
	}
} );

ASC.register( 'news-filter', function ( sandbox ) {
	var self, select, links, field, btn;

	return {
		init: function () {
			self = this;
			btn = $('.news-tag-btn');
			field = $('.news-tag-field');
			select = $('.news-tag-box');
			btn.bind('click',self.toggle);
			field.bind('click',self.toggle);
		},
		toggle: function () {
			select.stop(true,true).slideToggle();
		},
		destroy: function () {
			
		}
	}
} );

ASC.register( 'faqs', function ( sandbox ) {
	var self, questions, answers;
	return {
		init: function () {
			self = this;
			$('.answer').each( self.associateHeight );
			questions = $('.question-item')
						.find('.answer')
							.addClass('hidden')
							.css('opacity',0)
							.hide()
								.parent('.question-item')
								.bind('click', self.toggle);
		},
		associateHeight: function ( key, obj ) {
			var o = $(this);
			o.data( 'h', o.height() );	
			o.data( 'm', parseInt(o.css('margin-top')) );
		},
		toggle: function ( e ) {
			var q = $(this).toggleClass('active'),
				answer = q.find('.answer');
			answer.toggleClass('active');
			if( answer.hasClass('active') ) {
				answer.css({
					opacity: 0,
					display: 'block',
					height: 0
				}).stop().animate({
					height: answer.data('h'),
					marginTop: answer.data('m'),
					opacity: 1
				});
			}
			else {
				answer.stop().animate({
					height: 0,
					marginTop: 0,
					opacity: 0
				}, function () {
					answer.css('display', 'none');
				});
			}
		},
		destroy: function () {
			
		}
	}
} );

ASC.register( 'tertiary-navigation', function ( sandbox ) {
	var self, parents, sets;
	return {
		init: function () {
			self = this;
			sets = $('.sub-navigation').each( self.getHeight );
			$('.expanded').show();
			parents = $('.section-group.parent').not('.expanded').bind({
				mouseenter: self.twirlDown,
				mouseleave: self.twirlUp
			});
		},
		getHeight: function ( i,o ) {
			var obj = $(this);
			obj.data({
				h: obj.height(),
				mt: parseInt( obj.css('margin-top') ),
				mb: parseInt( obj.css('margin-bottom') ),
				pt: parseInt( obj.css('padding-top') ),
				pb: parseInt( obj.css('padding-bottom') )
			});	
		},
		twirlDown: function ( e ) {
			var group = $(this),
				children = group.find('.sub-navigation');
			
			if( !children.hasClass('expanded') ) {
				children.css({
					display: 'block',
					height: 0,
					opacity: 0
				});
				children.stop().animate({
					height: children.data('h'),
					marginTop: children.data('mt'),
					marginBottom: children.data('mb'),
					paddingTop: children.data('pt'),
					paddingBottom: children.data('pb'),
					opacity: 1
				}, 500);
				children.addClass('expanded');
			}
		},
		twirlUp: function ( e ) {
			e.stopImmediatePropagation();
			var group = $(this),
				children = group.find('.sub-navigation');
			
			if( children.hasClass('expanded') ) {
				children.removeClass('expanded');
				children.stop().animate({
					height: 0,
					marginTop: 0,
					marginBottom: 0,
					paddingTop:0,
					paddingBottom: 0,
					opacity: 0
				}, 500, function () {
					children.css('display', 'none');
				} );
			}
		},
		destroy: function () {
			
		}
	}
} );

$(function(){
	ASC.start( 'resize-watch' );
	ASC.start( 'background-adjust' );
	ASC.start( 'search' );
	ASC.start( 'sidebar-adjust' );
	if( $('.asc-map').length > 0 ) {
		ASC.start( 'map' );
	}
	if( $('.carousel').length > 0 ) {
		ASC.start('carousel');
	}
	if( $('.asc-submit-form').length > 0 ) {
		ASC.start( 'forms' );
	}
	if( $('#locations_map').length > 0 ) {
		ASC.start( 'locations' );
	}
	if( $('.tag-selection').length > 0 ) {
		ASC.start( 'news-dropdown' );
	}
	if( $('.bg-carousel-wrapper').length > 0 ) {
		ASC.start('home-carousel');
	}

	if( $('#news-tags').length > 0 ) {
		ASC.start('news-filter');
	}

	if( $('.question-set').length > 0 ) {
		ASC.start( 'faqs' );
	}

	if( $('.section-group.parent').length > 0 ) {
		ASC.start( 'tertiary-navigation' );
	}

	$(window).trigger('resize');
});
