(function (window, $) {
	var VIC = (function() {
	    
	    var map,
	    	infoWindow = new google.maps.InfoWindow({}),
	    	regionMarkers = [],
	    	vicMarkers = [],
	    	regions,
	    	loadingAnim = true,
	    	placeholders = {},
        	placeholderClassName = '';
	    
	    var vicMarkerImage = new google.maps.MarkerImage('/i/vic/all_year_vic_marker.png',
	        new google.maps.Size(28, 28),
	        new google.maps.Point(0,0),
	        new google.maps.Point(14,14)
	    );
	    
	    var seasonalMarkerImage = new google.maps.MarkerImage('/i/vic/seasonal_vic_marker.png',
	        new google.maps.Size(28, 28),
	        new google.maps.Point(0,0),
	        new google.maps.Point(14,14)
	    );
	    
	    var partnershipMarkerImage = new google.maps.MarkerImage('/i/vic/partnership_vic_marker.png',
	        new google.maps.Size(28, 28),
	        new google.maps.Point(0,0),
	        new google.maps.Point(14,14)
	    );
	    
	    var regionMarkerImage = new google.maps.MarkerImage('/i/vic/multi_marker_no_shadow.png',
	        new google.maps.Size(56, 46),
	        new google.maps.Point(0,0),
	        new google.maps.Point(28, 45)
	    );
	   
	    var shadow = new google.maps.MarkerImage('/i/vic/multi_marker_shadow.png',
            new google.maps.Size(56, 26),
            new google.maps.Point(0,0),
            new google.maps.Point(28, 25)
	    );
	    
	    var vicListingImage = "/i/vic/all_year_vic_image_thumb.png";
	    var seasonalListingImage = "/i/vic/seasonal_vic_image_thumb.png";
	    var partnershipListingImage = "/i/vic/partnership_vic_image_thumb.png";
	    
	    jQuery.expr[':'].Contains = function(a,i,m){
	    	return (a.textContent || a.innerText || "").toUpperCase().indexOf(m[3].toUpperCase())>=0;
	    };
	    
	    function sortVIC(a, b) {
	    	var nameA = a.name.toLowerCase();
	    	var nameB = b.name.toLowerCase();
	    	
	    	if (nameA < nameB) {
	    		return -1;
	    	} else if (nameA > nameB) {
	    		return 1;
	    	} else {
	    		return 0;
	    	}
	    }
	    
	    function useInputPlaceholder() {
	        return 'placeholder' in document.createElement('input');
	    }
	    
	    function setupPlaceholders() {
	        if (!useInputPlaceholder()) {
	            var formCount = 0;
	            
	            $('form').each(function () {
	                var form = $(this);
	                var id = form.attr('id');
	                
	                formCount++;
	                
	                // assign an ID if one not set
	                if (!id) {
	                    id = 'form-' + formCount;
	                    form.attr('id', id);
	                }
	                
	                form.find('input:text').each(function () {
	                    var input = $(this);
	                    var placeholderText = input.attr('placeholder');
	                    
	                    if (placeholderText !== '') {
	                        placeholders[id + '-' + input.attr('name')] = placeholderText;
	                        
	                        if (input.val() === '') {
	                            input.addClass(placeholderClassName).val(placeholderText);
	                        }
	                    }
	                }).focus(function () {
	                    var input = $(this);
	                    if (input.val() === placeholders[id + '-' + input.attr('name')]) {
	                        input.removeClass(placeholderClassName).val('');
	                    }
	                }).blur(function () {
	                    var input = $(this);
	                    if (input.val() === '' && placeholders[id + '-' + input.attr('name')]) {
	                        input.addClass(placeholderClassName).val(placeholders[id + '-' + input.attr('name')]);
	                    }
	                });
	                
	                // ensure placeholders don't get submitted
	                form.submit(function () {
	                    form.find('input:text').each(function () {
	                        var input = $(this);
	                        if (input.val() === placeholders[id + '-' + input.attr('name')]) {
	                            input.val('');
	                        }
	                    });
	                });
	            });
	        }
	    }

	    /**
	     * Creates region marker, VIC markers, and VIC list entries
	     */
	    function processRegion(region, index) {
	    	
	    	try {
				var markerTitle = region.name + ' (' + region.vicCount + ' Centres)';
				
				var latlng = new google.maps.LatLng(region.lat, region.lng);
				
				var regionMarker = new google.maps.Marker({
				    position: latlng,
				    shadow: shadow,
				    icon: regionMarkerImage,
				    title: markerTitle,
				    map: map
				});
				
				regionMarkers.push(regionMarker);
				
				google.maps.event.addListener(regionMarker, 'click', function() {
	                map.setZoom(8);
	                map.setCenter(regionMarker.getPosition());
	                refreshMap();
	            });
				
				var html = '<li><h3 class="regionheader">' + region.name + '</h3>' 
							+ '<ul class="region_' + index + '"></ul></li>';
				$('#vic_list').append(html);
				
		    	// sort list first
		    	region.vicList.sort(sortVIC);
            
				for (var i = 0; i < region.vicCount; i++) {
					processVIC(region.vicList[i], index);
				}
	    	} catch (exception) {
	    		// ignore
	    	}
	    }
	    
	    function processVIC(vic, regionIndex) {
			var vicLatLng = new google.maps.LatLng(vic.lat, vic.lng);
			
			var markerImage, listingImage;
			
			if (vic.type === 'VIC' && vic.period === 'All Year') {
				markerImage = vicMarkerImage;
				listingImage = vicListingImage;
			} else if (vic.type === 'VIC' && vic.period === 'Seasonal') {
				markerImage = seasonalMarkerImage;
				listingImage = seasonalListingImage;
			} else if (vic.type === 'PVIC') {
				markerImage = partnershipMarkerImage;
				listingImage = partnershipListingImage;
			}
			
			var vicMarker = new google.maps.Marker({
			    position: vicLatLng,
			    //shadow: shadow,
			    icon: markerImage,
			    title: vic.name
			});
			
			vicMarkers.push(vicMarker);
			
			var infoWindowContent = '<div class="vic_info"><h3>' + vic.name + '</h3><p>' + vic.address 
									+ '<br/>' + vic.postcode + '<br/>';
			
			if (vic.phone !== 'N/A') {
				infoWindowContent += vic.phone + '<br/>';
			}
			
			infoWindowContent += '<a href="mailto:'
								+ vic.email + '">' + vic.email + '</a></p>';
			
			if (vic.type === 'PVIC' && vic.hours !== '') {
				infoWindowContent += '<p>Opening Hours: ' + vic.hours + '</p>';
			}
			
			if (vic.type === 'VIC') {
				infoWindowContent += '<p>Opening period: ' + vic.period;
				
				if (vic.period === 'Seasonal') {
					infoWindowContent += ' (Apr-Oct)';
				}
				
				infoWindowContent += '</p>';
			}
			
			infoWindowContent += '<p><a href="http://maps.google.co.uk/maps?daddr=' 
								+ vic.postcode + '" onclick="window.open(this.href); return false;">Directions</a></p></div>';
			
			google.maps.event.addListener(vicMarker, 'click', function () {
                infoWindow.setContent(infoWindowContent);
                infoWindow.open(map, vicMarker);
            });
			
			if (loadingAnim) {
				$('li.loading').remove();
				loadingAnim = false;
			}
			
			var processedAddress = vic.address.replaceAll('<br/>', ', ').replaceAll('<br />', ', ') + ', ' + vic.postcode;
			var phoneNumber = vic.phone === 'N/A' ? '' : '<br/>' + vic.phone;
			
			var html = '<li class="index_' + (vicMarkers.length - 1) + '"><div class="thumb_container"><img src="'+listingImage+'" alt="thumbnail" /></div>'+'<div class="listing_content"><h3>' 
					+ vic.name + '</h3><p>' + processedAddress + phoneNumber + '</p></div></li>';
			
			$('ul[class=region_' + regionIndex + ']').append(html);
	    }
	    
	    function refreshMap() {	    	
	    	var toAdd, toRemove;
	    	var mapBounds = map.getBounds();
	    	
	    	if (map.getZoom() > 7) {
	    		toAdd = vicMarkers;
	    		toRemove = regionMarkers;
	    	} else {
	    		toAdd = regionMarkers;
	    		toRemove = vicMarkers;
	    	}
	    	
	    	for (var i = 0; i < toRemove.length; i++) {
	    		toRemove[i].setMap(null);
    		}
	    	
	    	for (var i = 0; i < toAdd.length; i++) {
	    		if (mapBounds.contains(toAdd[i].getPosition())) {
	    			toAdd[i].setMap(map);
	    		} else {
	    			toAdd[i].setMap(null);
	    		}
    		}
	    }
	    
	    function highlightVIC(index) {
	    	map.setZoom(8);
            map.setCenter(vicMarkers[index].getPosition());
            refreshMap();
	    	google.maps.event.trigger(vicMarkers[index], 'click');
	    }
	    
	    
	    return {
	        initialiseMapAndList: function (regionData, mapDivId, latitude, longitude, zoom, listId, filterInputName, placeHolderClass) {
	        	
	        	regions = regionData;
	        	
	            var latlng = new google.maps.LatLng(latitude, longitude);
	            var options = {
	                zoom: zoom,
	                center: latlng,
	                mapTypeId: google.maps.MapTypeId.ROADMAP,
	                navigationControl: true,
	                navigationControlOptions: {
	                    style: google.maps.NavigationControlStyle.ZOOM_PAN
	                }
	            };
	            map = new google.maps.Map($(mapDivId)[0], options);
	            
	            for (var i = 0; i < regions.length; i++) {
	                processRegion(regions[i], i);
	            }
	            
	            google.maps.event.addListener(map, 'zoom_changed', function () {
	            	refreshMap();
	            });
	            
	            google.maps.event.addListener(map, 'dragend', function () {
	            	refreshMap();
	            });
	            
	            $('input[name=' + filterInputName + ']').change(function () {
					var filter = $(this).val();
					if(filter) {
						$(listId).find('li:not(:Contains(' + filter + '))').hide();
						$(listId).find('li:Contains(' + filter + ')').show();
					} else {
						$(listId).find('li').show();
					}
					return false;
					})
				.keyup(function () {
		            $(this).change();
				}).bind('search', function () {
					$(this).change();
				});
	            
	            $('#vic_list li ul li').live('click', function () {
	            	$('#vic_list li ul li').removeClass('selected');
					var index = $(this).attr('class').replace('index_', '');
					$(this).addClass('selected');
					highlightVIC(index);
				});
	            
	            placeholderClassName = placeHolderClass;
	            setupPlaceholders();
	        }
	    };
	    
	})();
	
	window.VIC = VIC;
	
	String.prototype.replaceAll = function (stringToReplace, replacement) {
		var string = this;
		while (string.indexOf(stringToReplace) != -1) {
		    string = string.replace(stringToReplace, replacement);
		}
		return string;
	};
})(window, jQuery);
