var DealerWebsite = {};

DealerWebsite.Utils = {};

if (typeof (console) === "undefined") {
	console = {
		log : function() {
		}
	};
}

DealerWebsite.Utils.PostcodeValidation = {

	create : function() {
		var postcodeMatchRegEx = new RegExp(
		        "(A[BL]|B[ABDHLNRST]?|C[ABFHMORTVW]|D[ADEGHLNTY]|E[HNX]?|F[KY]|G[LUY]?|H[ADGPRSUX]|I[GMPV]|JE|K[ATWY]|L[ADELNSU]?|M[EKL]?|N[EGNPRW]?|O[LX]|P[AEHLOR]|R[GHM]|S[AEGKLMNOPRSTY]?|T[ADFNQRSW]|UB|W[ADFNRSV]|YO|ZE)[1-9]?[0-9]|([E|N|NW|SE|SW|W]1|EC[1-4]|WC[12])[A-HJKMNPR-Y]|[SW|W](([1-9][0-9]|[2-9])|EC[1-9][0-9]) [0-9][ABD-HJLNP-UW-Z]{2}");

		var external = {
		    validPostcode : function(postcode) {
			    return postcodeMatchRegEx.test(postcode.toUpperCase());
		    },

		    cleanPostcode : function(postcode) {
			    return postcode.replace(/(\s)/, '').toLowerCase();
		    },
		    isPostcodeEqual : function(postcode, dealerPostcode) {
			    var cleanedUserPostcode = this.cleanPostcode(postcode);
			    return cleanedUserPostcode === this
			            .cleanPostcode(dealerPostcode);
		    }
		};
		return external;
	}
};

DealerWebsite.Component = {};

DealerWebsite.Component.MapImage = {};
DealerWebsite.Component.MapImage.init = function(dealerPostcode,
        latitudeOverride, longitudeOverride, width, height) {
	var model = DealerWebsite.Component.MapImage.model();
	var view = DealerWebsite.Component.MapImageView(width, height);
	DealerWebsite.Component.MapImage.controller(model, view);
	model.updateMapImageComponent(dealerPostcode, latitudeOverride,
	        longitudeOverride);
};

DealerWebsite.Component.MapImage.model = function() {
	var postcodeValidation = DealerWebsite.Utils.PostcodeValidation.create();
	var dealerLocation = new DealerWebsite.Component.DealerMap.mapLocation();
	var self = {};
	self = {
	    updateMapImageComponent : function(dealerPostcode, latitudeOverride,
	            longitudeOverride) {
		    dealerLocation.setPostcode(dealerPostcode);
		    if ((latitudeOverride === null || latitudeOverride === undefined)
		            || (longitudeOverride === null || longitudeOverride === undefined)) {
			    if (postcodeValidation.validPostcode(dealerLocation
			            .getPostcode())) {
				    new DealerWebsite.GoogleMapsWrapper().fetchLocation(
				            dealerLocation.getPostcode(),
				            self.dealerLocationReceived,
				            self.onInvalidDealerLocation);
			    }
		    } else {
			    self
			            .dealerLocationReceived(latitudeOverride,
			                    longitudeOverride);
		    }
	    },

	    onInvalidDealerLocation : function() {
	    },

	    dealerLocationReceived : function(latitude, longitude) {
		    dealerLocation.setLocation(latitude, longitude);
		    self.displayMapImageComponent(dealerLocation);
	    },

	    displayMapImageComponent : function() {
	    }

	};

	return self;
};

DealerWebsite.Component.MapImage.controller = function(model, view) {

	model.displayMapImageComponent = function(dealerLocation) {
		view.displayMapImageComponentAndPopulateImageSrc(dealerLocation);
	};
};

function balanceMap() {
	$("div.left").height("100%");

	var leftHeight = $('div.left').height();
	var rightHeight = $('.right2').height() + 20;
	if (rightHeight > leftHeight) {
		$("div.left").height($(".right2").height() + 20);
		try {
			WebsiteManagement.getPageView().refreshBodyInitialHeight();
		} catch (a) {
		}
	}
}

DealerWebsite.Component.MapImageView = function(width, height) {
	var self = {
		displayMapImageComponentAndPopulateImageSrc : function(dealerLocation) {
			$('#dealerLocationImageComponent').attr('class',
			        'component rzc-find-us');
			$('.map img').attr(
			        'src',
			        'http://maps.google.com/maps/api/staticmap?center='
			                + dealerLocation.getLatitude() + ','
			                + dealerLocation.getLongitude() + '&zoom=12&size='
			                + width + 'x' + height
			                + '&maptype=roadmap&markers='
			                + dealerLocation.getLatitude() + ','
			                + dealerLocation.getLongitude() + '&sensor=false');
			setTimeout(balanceMap, 500);
		}
	};
	return self;
};

DealerWebsite.Component.DealerMap = {};

DealerWebsite.Component.DealerMap.init = function(dealerPostcode,
        latitudeOverride, longitudeOverride, shouldOutputTrackingTag) {
	var model = DealerWebsite.Component.DealerMap
	        .model(shouldOutputTrackingTag);
	var view = DealerWebsite.Component.DealerMapView.createLocationMap(model);
	DealerWebsite.Component.DealerMap.controller(model, view);
	model.updateDealerLocation(dealerPostcode, latitudeOverride,
	        longitudeOverride);
};

DealerWebsite.GoogleMapsWrapper = function() {
	var localSearch = new GlocalSearch();
	var locationHandler;
	var successHandler;
	var failHandler;
	var instance = this;
	var currentPostcode;

	var self = {};
	self = {
	    fetchLocation : function(postcode, successHandler, failHandler) {
		    currentPostcode = postcode;
		    instance.successHandler = successHandler;
		    instance.failHandler = failHandler;
		    localSearch.setSearchCompleteCallback(null, self.updateCallback);
		    localSearch.execute("\"" + postcode + "\"" + ", UK");
	    },

	    updateCallback : function() {
		    if (localSearch.results[0]) {
			    instance.successHandler(localSearch.results[0].lat,
			            localSearch.results[0].lng);
		    } else {
			    var errorText = 'Error executing search for ' + currentPostcode
			            + ':' + localSearch.bi;
			    console.log(errorText);
			    instance.failHandler(errorText);
		    }
	    }
	};

	return self;

};

DealerWebsite.Component.DealerMap.mapLocation = function() {
	var postcode;
	var latitude;
	var longitude;
	var instance = this;

	var self = {
	    setPostcode : function(postcode) {
		    instance.postcode = postcode;
	    },

	    setLocation : function(latitude, longitude) {
		    instance.latitude = latitude;
		    instance.longitude = longitude;
	    },

	    getLatitude : function() {
		    return instance.latitude;
	    },

	    getLongitude : function() {
		    return instance.longitude;
	    },

	    getPostcode : function() {
		    return instance.postcode;
	    }
	};

	return self;
};

DealerWebsite.Component.DealerMap.model = function(shouldOutputTrackingTag) {
	var postcodeValidation = DealerWebsite.Utils.PostcodeValidation.create();
	var dealerLocation = new DealerWebsite.Component.DealerMap.mapLocation();
	var userLocation = new DealerWebsite.Component.DealerMap.mapLocation();

	var self = {};
	self = {
	    updateDealerLocation : function(dealerPostcode, latitudeOverride,
	            longitudeOverride) {
		    dealerLocation.setPostcode(dealerPostcode);
		    if ((latitudeOverride === null || latitudeOverride === undefined)
		            || (longitudeOverride === null || longitudeOverride === undefined)) {
			    if (postcodeValidation.validPostcode(dealerLocation
			            .getPostcode())) {
				    new DealerWebsite.GoogleMapsWrapper().fetchLocation(
				            dealerLocation.getPostcode(),
				            self.dealerLocationReceived,
				            self.onInvalidDealerLocation);
			    } else if (dealerLocation.getPostcode().length > 0) {
				    self.onInvalidDealerLocation();
			    }
		    } else {
			    self
			            .dealerLocationReceived(latitudeOverride,
			                    longitudeOverride);
		    }
	    },

	    updateUserLocation : function(userPostcode) {
		    userLocation.setPostcode(userPostcode);
		    if (postcodeValidation.isPostcodeEqual(userPostcode, dealerLocation
		            .getPostcode())) {
			    self.onSameAsDealerPostcodeError();
		    } else if (postcodeValidation.validPostcode(userLocation
		            .getPostcode())) {
			    new DealerWebsite.GoogleMapsWrapper().fetchLocation(
			            userLocation.getPostcode(), self.userLocationReceived,
			            self.onUserPostcodeError);
		    } else {
			    self.onUserPostcodeError();
		    }
	    },

	    dealerLocationReceived : function(lat, longitude) {
		    dealerLocation.setLocation(lat, longitude);
		    self.onDealerLocationChanged();
	    },

	    userLocationReceived : function(lat, longitude) {
		    userLocation.setLocation(lat, longitude);
		    self.onUserLocationChanged();
	    },

	    getDealerLocation : function() {
		    return dealerLocation;
	    },

	    getUserLocation : function() {
		    return userLocation;
	    },

	    shouldOutputTrackingTag : function() {
		    return shouldOutputTrackingTag;
	    },

	    onInvalidDealerLocation : function(message) {
	    },
	    onSameAsDealerPostcodeError : function() {
	    },
	    onUserPostcodeError : function() {
	    },
	    onDealerLocationChanged : function() {
	    },
	    onUserLocationChanged : function() {
	    }
	};

	return self;
};

DealerWebsite.Component.DealerMap.controller = function(model, view) {
	view.onLoad = function() {
		model.updateLocation();
	};

	model.onDealerLocationChanged = function() {
		view.dealerLocationChanged();
	};

	model.onUserLocationChanged = function() {
		view.userLocationChanged();
	};

	model.onInvalidDealerLocation = function(message) {
		view.dealerPostcodeNotValid(message);
	};

	model.onSameAsDealerPostcodeError = function() {
		view.displaySameAsDealerPostcodeError();
	};

	model.onUserPostcodeError = function() {
		view.displayPostcodeError();
	};

};

DealerWebsite.Component.DealerMapView = {

	createLocationMap : function(model) {
		var directionsLink = $("a[rel='/relations/locationmap/directions']");

		DealerWebsite.Utils.PostcodeValidation.create();
		var internal = {};
		var external = {};
		external = {
		    drawMap : function() {
			    var point = new google.maps.LatLng(model.getDealerLocation()
			            .getLatitude(), model.getDealerLocation()
			            .getLongitude());
			    var myOptions = {
			        zoom : 17,
			        center : point,
			        scaleControl : true,
			        mapTypeId : google.maps.MapTypeId.ROADMAP
			    };
			    map = new google.maps.Map(
			            document.getElementById('google-map'), myOptions);
			    var markerOpts = {
			        position : point,
			        map : map,
			        visible : true
			    };
			    marker = new google.maps.Marker(markerOpts);
			    map.addMarker(marker);

		    },

		    displayDirectionsByAjax : function() {
			    var userPostcode = jQuery('#enterPostcode').val();
			    model.updateUserLocation(userPostcode);
		    },

		    dealerLocationChanged : function() {
			    external.drawMap(model);
		    },

		    userLocationChanged : function() {
			    internal.displayDirections();

		    },

		    dealerPostcodeNotValid : function(message) {
			    jQuery('.postcode-search form').remove();
			    jQuery('.map').remove();
			    jQuery('.top')
			            .append(
			                    "<div id='google-map'><p>We can't display the map and directions right now.<br />Please check again later.</p></div><!-- Error: "
			                            + message + '-->');
		    },

		    displayPostcodeError : function() {
			    if (jQuery('.error').is(':empty')) {
				    external.drawMap(model);
			    }
			    jQuery('.error')
			            .html(
			                    "Your postcode hasn't been recognised, please re-enter");
			    jQuery('#directions').empty();
			    directionsLink.addClass("rzc-hidden");
		    },

		    displaySameAsDealerPostcodeError : function() {
			    if (jQuery('.error').is(':empty')) {
				    external.drawMap(model);
			    }
			    jQuery('.error').html(
			            "Your postcode is the same as our postcode");
			    jQuery('#directions').empty();
			    directionsLink.addClass("rzc-hidden");
		    },

		    injectTrackingTags : function() {
			    var evastr0000 = "";
			    if (!ID_dcode_15243615) {
				    ID_dcode_15243615 = "";
			    }
			    if (!ID_tt_15243615) {
				    ID_tt_15243615 = "k";
			    }

			    evastr0000 = "&rq=" + escape(document.location);
			    evastr0000 += "&dc=" + escape(ID_dcode_15243615);

			    // get keydata values
			    if (!ID_CT_ID_32145632) {
				    ID_CT_ID_32145632 = "";
			    }
			    if (!ID_CT_VALUE_32145632) {
				    ID_CT_VALUE_32145632 = "";
			    }
			    evastr0000 += "&userid=" + escape(ID_uid_15243615);
			    evastr0000 += "&tt=" + escape(ID_tt_15243615);
			    evastr0000 += "&ctid=" + escape(ID_CT_ID_32145632);
			    evastr0000 += "&ctval=" + escape(ID_CT_VALUE_32145632);

			    var now = new Date();

			    var thetimeid = now.getTime();

			    evastr0000 += "&tc=" + thetimeid;

			    var scriptTag = document.createElement("img");
			    scriptTag.setAttribute("border", "0");
			    scriptTag.setAttribute("alt", "eVisit");
			    scriptTag.setAttribute("width", "1");
			    scriptTag.setAttribute("height", "1");
			    scriptTag.setAttribute("class", "directionsTracking");
			    scriptTag.setAttribute("src",
			            "http://extra.evisitanalyst.com/at/tagkd.php?"
			                    + evastr0000);

			    document.body.appendChild(scriptTag);
		    }

		};

		internal = {

		    displayDirections : function() {

			    var dealerPoint = new google.maps.LatLng(model
			            .getDealerLocation().getLatitude(), model
			            .getDealerLocation().getLongitude());
			    var userPoint = new google.maps.LatLng(model.getUserLocation()
			            .getLatitude(), model.getUserLocation().getLongitude());

			    document.getElementById("directions").innerHTML = '';
			    directionsDisplay = new google.maps.DirectionsRenderer();

			    map.clearMarkers();

			    var directionsRequest = {
			        origin : userPoint,
			        travelMode : google.maps.DirectionsTravelMode.DRIVING,
			        unitSystem : google.maps.DirectionsUnitSystem.IMPERIAL,
			        destination : dealerPoint,
			        region : "uk"
			    };

			    var directionsService = new google.maps.DirectionsService();
			    directionsService
			            .route(
			                    directionsRequest,
			                    function(result, status) {
				                    if (status === google.maps.DirectionsStatus.OK) {
					                    var dirs = document
					                            .getElementById("directions");
					                    directionsDisplay.setPanel(dirs);
					                    directionsDisplay.setMap(map);
					                    directionsDisplay.setDirections(result);
					                    map.addMarker(directionsDisplay);
					                    jQuery('.error').empty();
					                    directionsLink
					                            .removeClass("rzc-hidden");
				                    } else if (status === google.maps.DirectionsStatus.ZERO_RESULTS) {
					                    jQuery('.error')
					                            .html(
					                                    "We could not calculate directions between "
					                                            + model
					                                                    .getUserLocation()
					                                                    .getPostcode()
					                                            + " and "
					                                            + model
					                                                    .getDealerLocation()
					                                                    .getPostcode());
					                    directionsLink.addClass("rzc-hidden");
				                    } else {
					                    directionsLink.addClass("rzc-hidden");
					                    console.log(result);
				                    }
			                    });
		    },

		    bindTrackingScriptToFormSubmit : function() {
			    if (model.shouldOutputTrackingTag()) {
				    jQuery('.postcode-search form').bind('submit', function() {
					    external.injectTrackingTags();
					    return false;
				    });
			    }
		    },

		    bindAjaxDirectionsToFormSubmit : function() {
			    jQuery('.postcode-search form').bind('submit', function() {
				    external.displayDirectionsByAjax();
				    return false;
			    });
		    },

		    extendGoogleMapForMarkers : function() {
			    var i;
			    google.maps.Map.prototype.markers = [];

			    google.maps.Map.prototype.addMarker = function(marker) {
				    this.markers[this.markers.length] = marker;
			    };

			    google.maps.Map.prototype.getMarkers = function() {
				    return this.markers;
			    };

			    google.maps.Map.prototype.clearMarkers = function() {
				    for (i = 0; i < this.markers.length; i++) {
					    this.markers[i].setMap(null);
				    }
				    this.markers = [];
			    };
		    }
		};

		internal.extendGoogleMapForMarkers();
		internal.bindAjaxDirectionsToFormSubmit();
		internal.bindTrackingScriptToFormSubmit();

		jQuery('#enterPostcode').val("");

		return external;
	}
};

function initialiseLocationMap(postcode, latitudeOverride, longitudeOverride,
        shouldOutputTrackingTag) {
	var locationMap = DealerWebsite.Component.DealerMap.init(postcode,
	        latitudeOverride, longitudeOverride, shouldOutputTrackingTag);
}

function initialiseMapImageComponent(postcode, latitudeOverride,
        longitudeOverride, width, height) {
	DealerWebsite.Component.MapImage.init(postcode, latitudeOverride,
	        longitudeOverride, width, height);
}

