(function($) {
	
	/*
	 *  Class "isUsed" applied if input has text in it or is focused.
	 */
	$.fn.isUsed = function(params) {
		var defaults = {};
		var options =  $.extend(defaults, params);
		
		this.each(function() {
			var $t = $(this);
			
			if ($t.val() !== '') {
				$t.addClass('isUsed');
			};
			
			$t.focus(function () {
				$t.addClass('isUsed');
			}).blur(function () {
				if ($t.val() === '') {
					$t.removeClass('isUsed');
				};
			});
		});
		return this; 
	};
	
	/*
	 *  tickertape
	 */
	$.fn.tickertape = function (params) {
		var defaults = {
				speed: 4000,
				scrollSpeed: 10000
		};
		var options =  $.extend(defaults, params);
		
        var targets = this;
        var length = targets.length;
        
        var show = function(i) {
        	var obj = targets.siblings(":nth-child(" + i + ")");
        	var currWidth = obj.width();
        	obj.css({'left': '-' + currWidth + 'px'});
        	obj.fadeIn(options.speed, function () {
        		var j = (i - 1)%length;
                show(j);
        		obj.animate({'left': '900px'}, options.scrollSpeed, function () {
        		});
            });
        }
        show(length);
        
		return this; 
	};
	
	/*
	 *  slideshow
	 */
	$.fn.slideshow = function (params) {
		var defaults = {
				speed: 1000,
				pause: 2000
		};
		var options =  $.extend(defaults, params);
		
        var targets = this;
        targets.css({'z-index':'0'});
        var length = targets.length;
        var show = function(i) {
        	var toShow = targets.filter(":nth-child(" + i + ")");
        	toShow.css({'z-index':'1'});
            toShow.fadeIn(options.speed, function () {
            	hide(i);
            });
        }
        var hide = function(i) {
        	var j = i%length + 1;
        	
        	
        	window.setTimeout(function() {
        		show(j);
            	var toHide = targets.filter(":nth-child(" + i + ")");
            	toHide.css({'z-index':'0'});
            	toHide.fadeOut(options.speed, function () {  
                });
        	}, options.pause);
        }
        if ( length !== 1 ) {
        	show(1);
        } else {
        	targets.fadeIn(options.speed);
        }
        
		return this; 
	};
	
	/*
	 *  oddEven
	 */
	$.fn.oddEven = function (params) {
		var defaults = {
			target: 'tr',
			oddClass: 'odd',
			evenClass: 'even'
		};
		var options =  $.extend(defaults, params);
		
		this.each(function() {
			var $t = $(this);
			$t.find(options.target + ':odd').addClass(options.oddClass);
			$t.find(options.target + ':even').addClass(options.evenClass);
		});
        
		return this; 
	};
	
	$.fn.stripe = function (params) {
		var defaults = {
			
		};
		var options = $.extend(defaults, params);
		
		this.each(function () {
			$(this).find('tr:even:not(:first)').addClass('evenrow');
			$(this).find('tr:first').addClass('tabletopheader');
			$(this).find('tr:nth-child(2)').addClass('tableheader');
		});
		
	};
	
	$.fn.fms = function (t) {
		var defaults = {
			stopNumber: '',
			stopText: '',
			stopClickedCallBack: function (number) {
				//override
			},
			mapSearchCallBack: function (searchString) {
				//override
			}
		};
		var t = $.extend(defaults, t);
		
		return this.each(function () {
			
			var obj = $(this);
			
			var iconWidth = 65;
		    var iconHeight = 27;
			
			var startLatLng = new google.maps.LatLng(-36.8442, 174.7676);
			currLatLng = startLatLng; /*keep track of current pos*/
			
			/*
			 * Auckland bounds
			 * */
			var southWest = new google.maps.LatLng(-37.3111,174.3887);
			var northEast = new google.maps.LatLng(-36.0579,175.2786);
			var startBounds = new google.maps.LatLngBounds(southWest,northEast);
			
			/*
			 * Google map objects
			 * */
			var geocoder  = new google.maps.Geocoder();
			
			var map = new google.maps.Map(obj.get(0), {
				zoom: 17,
				center: startLatLng,
				mapTypeId: google.maps.MapTypeId.ROADMAP,
				mapTypeControlOptions: {
					mapTypeIds: [google.maps.MapTypeId.ROADMAP,google.maps.MapTypeId.SATELLITE,google.maps.MapTypeId.HYBRID]
				}
			});
			
			/*marker stack*/
			var markers = {};
			
			/*
			 * Capture zoom event to hide marker (idle fires after the zoom event)
			 * */
			google.maps.event.addListener(map, 'zoom_changed', function() {
				if ( map.getZoom() < 17 ) {
					
					$.each(markers, function (i, n) {
						n.hide();
					});
				}
			});
			
			/*
			 * Capture idle event (after map zoom or drag changes)
			 * */
			google.maps.event.addListener(map, 'idle', function() {
				
				/*map viewing bounds*/
				var bounds = map.getBounds();
				NE = bounds.getNorthEast();
				SW = bounds.getSouthWest();
				
				/*
				 * snap bounds to 100th of a degree ~1.2km (enables cacheable queries)
				 * */
				var latMin = Math.floor(SW.lat()*100)/100;
				var latMax = Math.ceil(NE.lat()*100)/100;
				var lngMin = Math.floor(SW.lng()*100)/100;
				var lngMax = Math.ceil(NE.lng()*100)/100;
				
				/*
				 * if the map (grid) bounds have changed request stops and add to makers stack
				 * */
				if ( map.getZoom() > 16 ) {
					
					/*
					 * Call web service to get additional stops
					 * */
					$.ajax({
			        	url: '/services/stops_by_geo_area.cfm',
			        	data: {
			        		'latMin':latMin,
			        		'latMax':latMax,
			        		'longMin':lngMin,
			        		'longMax':lngMax
			        	},
			        	dataType: 'json',
			        	cache: true,
			        	beforeSend: function () {
						},
			        	success: function(data) {
							
							/*
							 * Add stop is not already in the marker stack
							 * */
			        		$.each(data['data']['number'], function (i, n) {
			        			
			        			if ( n*1 > 999 && n*1 < 8999 ) {
			        				
				        			if( !markers[n] ) {
				        				
				        				markers[n] = (new InfoBox({
					        				content: '<div title="' + data['data']['location'][i] + '" ' +
					        				'data-isactive="' + data['data']['isactive'][i] + '" ' +
					        				'data-isrealtime="' + data['data']['isrealtime'][i] + '" ' +
					        				'data-lat="' + data['data']['lat'][i] + '" ' +
					        				'data-long="' + data['data']['long'][i] + '" ' +
					        				'data-mode="' + data['data']['mode'][i] + '" ' +
					        				'data-number="' + n + '">' + n + '</div>',
					        				position: new google.maps.LatLng(data['data']['lat'][i], data['data']['long'][i]),
					        				boxStyle: {
					                        	color: '#FFFFFF',
					                        	padding: '10px 0 0 6px',
					                        	fontSize: '8pt',
					                        	height: '18px',
					                        	width: '60px',
					                        	background: 'url(\'/images/stop-small.png\') no-repeat scroll 0 0 transparent',
					                        	cursor: 'pointer'
					        				},
					        				disableAutoPan: true,
					        				closeBoxURL: "",
					        				isHidden: false,
					        				pane: "mapPane",
					        				pixelOffset: new google.maps.Size(-iconWidth/2, -iconHeight/2),
					        				enableEventPropagation: true
					        			}));
					        			markers[n].open(map);
				        			} else {
				        				
				        				markers[n].show();
				        			}
			        			}
			        		});
			          	},
			          	error: function(req, status) {
			          		/*an error occurred - nothing can be done in this case*/
			          	}
			        });
				}
			});
			
			/*
			 * Bind events to regain map focus
			 * */
			obj.bind('resize', function () {
				obj.width(obj.parent().width());
				obj.height(obj.parent().height());
				google.maps.event.trigger(map, 'resize');
				
			}).bind('show', function () {
				obj.width(obj.parent().width());
				obj.height(obj.parent().height());
				google.maps.event.trigger(map, 'resize');
				$('.googleMapSearch', obj.parent()).val(defaultSearchString());
				focusMap(defaultSearchString());
				
			}).bind('hide', function () {
				
			}).bind('updateStopNumber', function (e, stopNumber) {
				t.stopNumber = stopNumber;
				
			}).bind('updateStopText', function (e, stopText) {
				t.stopText = stopText;
				
			});
			
			/*
			 * When the infoBox is clicked fire the stopClickedCallBack (infoBox does not provide native click events)
			 * */
			obj.delegate('[data-number]', 'click', function () {
				t.stopClickedCallBack({
					number: $(this).attr('data-number'),
					location: $(this).attr('title'),
					isactive: $(this).attr('data-isactive'),
					isrealtime: $(this).attr('data-isrealtime'),
					lat: $(this).attr('data-lat'),
					long: $(this).attr('data-long'),
					mode: $(this).attr('data-mode')
				});
			});
			
			/*
			 * Return default search string (stop number is default)
			 * */
			var defaultSearchString = function () {
				return (t.stopNumber !=='' ? t.stopNumber : t.stopText);
			}
			
			/*
			 * Focus the map - first checks to see if the searchString is a stopNumber else uses google maps
			 * */
			var focusMap = function (searchString) {
				
				if ( $.trim(searchString) !== '' ) {
					$.ajax({
			        	url: '/services/stops_by_number.cfm',
			        	data: {
			        		'stops':searchString
			        	},
			        	dataType: 'json',
			        	cache: true,
			        	beforeSend: function () {
						},
			        	success: function(data) {
							if ( data['recordcount'] > 0 ) {
								currLatLng = new google.maps.LatLng(data['data']['lat'][0], data['data']['long'][0])
								map.setZoom(17);
								map.setCenter(currLatLng)
							} else {
								geocoder.geocode( { 'address': searchString, 'bounds': startBounds}, function(results, status) {
									if (status == google.maps.GeocoderStatus.OK) {
									
										/*iterate through the results and end on the first valid*/
										$.each(results, function (i, n) {
											
											if ( n.geometry.location.lat() > southWest.lat() && n.geometry.location.lat() < northEast.lat() && n.geometry.location.lng() > southWest.lng() && n.geometry.location.lng() < northEast.lng() ) {
												/*result is within Auckland bounds*/
												currLatLng = n.geometry.location;
												map.setZoom(17);
												map.setCenter(currLatLng);
												return false;
												
											} else if ( i === results.length-1 ) {
												/*even the last result wasn't valid so load default*/
												currLatLng = startLatLng;
												map.setZoom(17);
												map.setCenter(currLatLng);
											}
										});
										
									} else {
										/*error occurred or no results*/
										currLatLng = startLatLng;
										map.setZoom(17);
										map.setCenter(currLatLng);
									}
								});
							}
						},
			          	error: function(req, status) {
							currLatLng = startLatLng;
							map.setZoom(17);
							map.setCenter(currLatLng);
			          	}
					});
				} else {
					currLatLng = startLatLng;
					map.setZoom(17);
					map.setCenter(currLatLng);
				}
				t.mapSearchCallBack(searchString);
			};
			
			/*
			 * Set up the internal map form
			 * */
			(function () {
				obj.parent().css('position','relative');
				obj.after( '<form action="none" style="left: 100px; position: absolute; top: 14px;">' +
						'<input class="googleMapSearch" type="textbox" value="" style="width:200px;"/>' +
						'<input id="encode" type="submit" value="Search" style="background-color: white; border: 1px solid black; margin-left:4px; padding:0 4px 0 4px;" />' + 
					'</form>'
				);
				$('.googleMapSearch', obj.parent()).val(defaultSearchString());
				
				$('form', obj.parent()).submit(function () {
					focusMap($('.googleMapSearch', obj.parent()).val());
					return false;
				});
			}());
		});
	};
	
	$.fn.journeyLegMap = function (t) {
		var defaults = {
			lat:-36.888707,
			lng:174.756038,
			details: {
				'mode':'Walk',
				'fromCoords':[-36.8458739705122,174.762720112748],
				'toCoords':[-36.8450217786248,174.770671757463],
				'fromLocation':'26 Hobson St',
				'toLocation':'Britomart Place,  Auckland Central',
				'wayptsCoords': false
			}
		};
		var t = $.extend(defaults, t);
		
		var startLatLng,endLatLng;
		
		startLatLng = new google.maps.LatLng(t.details.fromCoords[0],t.details.fromCoords[1]);
		endLatLng = new google.maps.LatLng(t.details.toCoords[0],t.details.toCoords[1]);
		
		var stopNumbers = [t.details.fromStopNumber, t.details.toStopNumber];
		var latLngs = [startLatLng, endLatLng];
		
		var iconWidth = 65;
		var iconHeight = 27;
		var icons = ['/images/dd-start.png', '/images/dd-end.png'];
		var stopIcons = {
			'Bus':'/images/markers/bus.png',
			'Train':'/images/markers/train.png',
			'Ferry':'/images/markers/ferry.png'
		};
		
		return this.each(function () {
			
			var obj = $(this);
			
			var map;
			
			obj.bind('show', function () {
				
				/*Map is instantiated every time the [dom]map is shown due to bug with directions service*/
				map = new google.maps.Map(this, {
					zoom: 17,
					center: (new google.maps.LatLng(t.lat,t.lng)), 
					mapTypeId: google.maps.MapTypeId.ROADMAP,
					mapTypeControlOptions: {
						mapTypeIds:[]
					}
				});
				
				var bounds = new google.maps.LatLngBounds();
				
				$.each(latLngs, function (i, n) {
					var marker = new google.maps.Marker({
						position: n, 
						map: map, 
						title:'Walk Start',
						icon: icons[i]
					});
					bounds.extend(n);
				});
				
				map.fitBounds(bounds);
				
				$.each(stopNumbers, function (i, n) {
					if (n) {
						$.ajax({
				        	url: '/services/stops_by_number.cfm',
				        	data: {
				        		'stops':n
							},
							dataType: 'json',
							cache: true,
							beforeSend: function () {
							},
							success: function(response) {
								//alert(response);
								marker = (new InfoBox({
									content: '<div title="' + response['data']['location'] + '" style="text-align:left;">' + (n > 999 ? n : '') + '</div>',
									position: latLngs[i],
									boxStyle: {
										color: '#FFFFFF',
										padding: '10px 0 0 6px',
										fontSize: '8pt',
										height: '18px',
										width: '60px',
										background: 'url(\'' + stopIcons[response['data']['mode']] + '\') no-repeat scroll 0 0 transparent',
										cursor: 'pointer'
									},
									disableAutoPan: true,
									closeBoxURL: "",
									isHidden: false,
									pane: "mapPane",
									pixelOffset: new google.maps.Size(-iconWidth/2, -iconHeight/2),
									enableEventPropagation: true
								}));
								marker.open(map);
							},
							error: function(req, status) {
								/*an error occurred - nothing can be done in this case*/
							}
						});
					}
				});
				
				google.maps.event.addListener(map, 'idle', function() {
					google.maps.event.trigger(map, 'resize');
				});
			});
		});
	};
	
	/*
	 * [Another plug-in can go below here...]
	 */
})(jQuery);