function isSet( variable )
{
	return( typeof( variable ) != 'undefined' );
}

if (!isSet(mapsOnPage)) {
	var mapsOnPage = new Array();
}

function loadAllMaps() {
	for(i = 0; i < mapsOnPage.length; i++) {
		mapsOnPage[i].load();
	}	
}

function AliziumMap(mapElement, streetElement, streetViewElement, mapViewElement) {
	mapsOnPage.push(this);
	
	this.markers = new Array();
	
	this.mapElement = mapElement;
	this.streetElement = streetElement;
	this.streetViewElement = streetViewElement;
	this.mapViewElement = mapViewElement;
	
	this.latitude;
    this.longitude;
    this.hotelName;
    this.address;
	
	this.map;
    this.isStreetView = false;
    this.hasStreetView = false;
    this.currentLat;
    this.currentLng;
    this.locationName;
    this.previousLat,
	this.previousLng;
    this.countLocation = 3;
    this.maxLocationListed = 17 + 1;
	
	this.cityCenterLatitude;
	this.cityCenterLongitude;
	
	/* error codes */
    this.NO_NEARBY_PANO = 600;       /* No panorama data was found. (Since 2.104) */
	this.FLASH_UNAVAILABLE = 603;
}

AliziumMap.prototype.setLatitude = function(latitude) {
	this.latitude = latitude;
	this.currentLat = latitude;
}

AliziumMap.prototype.setLongitude = function(longitude) {
	this.longitude = longitude;
	this.currentLng = longitude; 
}

AliziumMap.prototype.setCityCenterLatitude = function(latitude) {
	this.cityCenterLatitude = latitude;	
}

AliziumMap.prototype.setCityCenterLongitude = function(longitude) {
	this.cityCenterLongitude = longitude;	
}

AliziumMap.prototype.setHotelName = function(hotelName) {
	this.hotelName = hotelName;
	this.locationName = hotelName;
}

AliziumMap.prototype.setAddress = function(address) {
	this.address = address;
}

AliziumMap.prototype.addGmarker = function(latitude, longitude) {
	var latlng = new GLatLng(latitude, longitude);
	marker = new GMarker(latlng);
	this.markers.push(marker);
}

AliziumMap.prototype.load = function() {
		if (GBrowserIsCompatible()) {
            this.map = new GMap2(this.mapElement);
            this.map.setCenter(new GLatLng(this.latitude, this.longitude), 13);
            this.map.addControl(new GLargeMapControl3D());
            this.map.addControl(new GMapTypeControl());
            this.map.addControl(new GScaleControl());

            var latlng = new GLatLng(this.latitude, this.longitude);
            marker = new GMarker(latlng);
            this.map.addOverlay(marker);
			
			for (j = 0; j < this.markers.length; j++) {
				this.map.addOverlay(this.markers[j]);
			}

            var mt = new Pointer(marker, this.map);

            /* Create our "tiny" marker icon */
            var tinyIcon = new GIcon();
            tinyIcon.image = "http://hotelscombined.com/Images/marker_20_green.png";
            tinyIcon.shadow = "http://hotelscombined.com/Images/marker_20_shadow.png";
            tinyIcon.iconSize = new GSize(12, 20);
            tinyIcon.shadowSize = new GSize(22, 20);
            tinyIcon.iconAnchor = new GPoint(6, 20);
            tinyIcon.infoWindowAnchor = new GPoint(5, 1);

            /* Set up our GMarkerOptions object literal */
            markerOptions = { icon: tinyIcon };

			var point = new GLatLng(this.cityCenterLatitude, this.cityCenterLongitude);
            marker = new GMarker(point, markerOptions);
            GEvent.addListener(marker, "click", function() {
                this.addmarker(this.cityCenterLatitude, this.cityCenterLongitude, "City Center");
            });
            this.map.addOverlay(marker);
     }
}

AliziumMap.prototype.addmarker = function(lat, lng, text) {
	this.currentLat = lat;
	this.currentLng = lng;
	this.locationName = text;
	if (this.isStreetView) {
		this.addStreetView(lat, lng, false);
	}
	else {
		this.openWindow(lat, lng, text);
	}
}

AliziumMap.prototype.changeLocation = function(index, lat, lng, text) {
	if (index != 0)
	{
		this.addmarker(lat, lng, text);
	}
}

AliziumMap.prototype.openWindow = function(lat, lng, text) {
	this.map.openInfoWindowHtml(new GLatLng(lat, lng), '<' + 'div style="visibility:hidden;">infoHeader</d' + 'iv><d' + 'iv style="font-size: 12px; font-family: Arial,sans-serif; text-align: center;">' + text + '</di' + 'v>');
}

AliziumMap.prototype.addStreetView = function(lat, lng, fromMapView) {
	var hotelPano, hotelLocation;
	this.hasStreetView = true;
	this.hotelLocation = new GLatLng(lat, lng);
	panoramaOptions = { latlng:this.hotelLocation};
	
	hotelPano = new GStreetviewPanorama(this.streetElement, panoramaOptions);
	if (fromMapView)
	{
		GEvent.addListener(hotelPano, "error", this.handleNoFlashFromMapView);
	} else
	{
		GEvent.addListener(hotelPano, "error", this.handleNoFlash);
	}
}

AliziumMap.prototype.streetView = function() {
	var flag = false;
		if (this.currentLat == this.previousLat) if (this.currentLng == this.previousLng) if (this.hasStreetView) flag = true;
	/* load the street view if previous street view isn't same as current location */
	if (flag == false) {
		this.addStreetView(this.currentLat, this.currentLng, true);
	}
	this.streetElement.style.display = 'block';
	this.mapElement.style.display = 'none';
	this.streetViewElement.style.display = 'none';
	this.mapViewElement.style.display = 'block';
	$(".noView").addClass("displayNone");
	this.isStreetView = true;
}

AliziumMap.prototype.mapView = function() {
	this.streetElement.style.display = 'none';
	this.mapElement.style.display = 'block';
	this.streetViewElement.style.display = 'block';
	this.mapViewElement.style.display = 'none';
	this.isStreetView = false;
	this.previousLat = this.currentLat;
	this.previousLng = this.currentLng;
	this.openWindow(this.currentLat, this.currentLng, this.locationName);
	$(".noView").removeClass("displayNone");
}

AliziumMap.prototype.handleNoFlash = function(errorCode) {
	if (errorCode == this.NO_NEARBY_PANO) {
		alert("Street view is not available for this location");
		this.hasStreetView = false;
		return;
	}
	else
	{
		if (errorCode == this.FLASH_UNAVAILABLE) {
			alert("Error: Flash doesn't appear to be supported by your browser");
			this.hasStreetView = false;
			return;
		}
	}
}

AliziumMap.prototype.handleNoFlashFromMapView = function(errorCode) {
	if (errorCode == this.NO_NEARBY_PANO) {
		alert("Street view is not available for this location");
		this.hasStreetView = false;
		this.mapView();
		return;
	}
	else
	{
		if (errorCode == this.FLASH_UNAVAILABLE) {
			alert("Error: Flash doesn't appear to be supported by your browser");
			this.hasStreetView = false;
			this.mapView();
			return;
		}
	}
}

/* Creates a Pointer for the given marker and displays it ont he map as needed. */
function Pointer(marker, map) {
	this.map_ = map;
	this.marker_ = marker;
	this.enabled_ = true;
	this.arrowDisplayed_ = false;
	this.arrow_ = null;
	this.oldArrow_ = null;
	this.control_ = null;

	this.iconScale_ = 0.6;
	this.padding_ = 65;
	this.color_ = '#0000ff';
	this.weight_ = 10;
	this.length_ = 10;
	this.opacity_ = 0.6;
	this.updateEvent_ = 'move';
	this.panEvent_ = 'click';
	this.quickPanEnabled_ = true;

	/* replicate a different sized icon  */
	var babyIcon = new GIcon(marker.getIcon());
	babyIcon.iconSize = new GSize(
			marker.getIcon().iconSize.width * this.iconScale_,
			marker.getIcon().iconSize.height * this.iconScale_);
	babyIcon.iconAnchor = new GPoint(
			marker.getIcon().iconAnchor.x * this.iconScale_,
			marker.getIcon().iconAnchor.y * this.iconScale_ / 2);
	/* kill the shadow  */
	babyIcon.shadow = null;
	this.babyMarker_ = new GMarker(new GPoint(0, 0), babyIcon);

	/* bind the update task to the event trigger */
	GEvent.bind(this.map_, this.updateEvent_, this, this.updateArrow_);
	/* update the arrow if the marker moves */
	GEvent.bind(this.marker_, 'changed', this, this.updateArrow_);
	if (this.quickPanEnabled_) {
		GEvent.bind(this.babyMarker_, this.panEvent_, this, this.panToMarker_);
	}

	/* do an inital check */
	this.updateArrow_();
}
;

/* Disables the pointer. */
Pointer.prototype.disable = function() {
	this.enabled_ = false;
	this.updateArrow_();
};

/* Enables the pointer. */
Pointer.prototype.enable = function() {
	this.enabled_ = true;
	this.updateArrow_();
};

/* Called on on the trigger event to update the arrow. Primary function is to */
/* check if the parent marker is in view, if not draw the tracking arrow. */
Pointer.prototype.updateArrow_ = function() {
	var flag = false;
		if (!this.map_.getBounds().containsLatLng(this.marker_.getLatLng())) if (this.enabled_) flag = true;
	if (flag == true) {
		this.drawArrow_();
	} else if (this.arrowDisplayed_) {
		this.hideArrow_();
	}
};

/* Draws or redraws the arrow as needed, called when the parent marker is */
/* not with in the map view. */
Pointer.prototype.drawArrow_ = function() {
	/* convert to pixels */
	var bounds = this.map_.getBounds();
	var SE = this.map_.fromLatLngToDivPixel(bounds.getSouthWest());
	var NE = this.map_.fromLatLngToDivPixel(bounds.getNorthEast());
	/* include the padding while deciding on the arrow location */
	var minX = SE.x + this.padding_;
	var minY = NE.y + this.padding_;
	var maxX = NE.x - this.padding_;
	var maxY = SE.y - this.padding_;

	/* find the geometric info for the marker realative to the center of the map */
	var center = this.map_.fromLatLngToDivPixel(this.map_.getCenter());
	var loc = this.map_.fromLatLngToDivPixel(this.marker_.getLatLng());

	/* get the slope of the line */
	var m = (center.y - loc.y) / (center.x - loc.x);
	var b = (center.y - m * center.x);

	/* end the line within the bounds */
	  var flag = false;
	  if (loc.x < maxX) if(loc.x > minX) flag =true;
	if (flag == true) {
		var x = loc.x;
	} else if (center.x > loc.x) {
		var x = minX;
	} else {
		var x = maxX;
	}

	/* calculate y and check boundaries again   */
	var y = m * x + b;
	if (y > maxY) {
		y = maxY;
		x = (y - b) / m;
	} else if (y < minY) {
		y = minY;
		x = (y - b) / m;
	}

	/* get the proper angle of the arrow */
	var ang = Math.atan(-m);
	if (x > center.x) {
		ang = ang + Math.PI;
	}

	/* define the point of the arrow */
	var arrowLoc = this.map_.fromDivPixelToLatLng(new GPoint(x, y));

	/* left side of marker is at -1,1 */
	var arrowLeft = this.map_.fromDivPixelToLatLng(
			this.getRotatedPoint_(((-1) * this.length_), this.length_, ang, x, y));

	/* right side of marker is at -1,-1 */
	var arrowRight = this.map_.fromDivPixelToLatLng(
			this.getRotatedPoint_(((-1) * this.length_), ((-1) * this.length_), ang, x, y));


	var center = this.map_.getCenter();
	var loc = this.marker_.getLatLng();

	this.oldArrow_ = this.arrow_;
	this.arrow_ = new GPolyline([arrowLeft, arrowLoc, arrowRight],
			this.color_, this.weight_, this.opacity_);
	this.map_.addOverlay(this.arrow_);

	/* move the babyMarker to -1,0 */
	this.babyMarker_.setLatLng(this.map_.fromDivPixelToLatLng(
			this.getRotatedPoint_(((-2) * this.length_), 0, ang, x, y)));

	if (!this.arrowDisplayed_) {
		this.map_.addOverlay(this.babyMarker_);
		this.arrowDisplayed_ = true;
	}
	if (this.oldArrow_) {
		this.map_.removeOverlay(this.oldArrow_);
	}
};

/* Hides the arrows. */
Pointer.prototype.hideArrow_ = function() {
	this.map_.removeOverlay(this.babyMarker_);
	if (this.arrow_) {
		this.map_.removeOverlay(this.arrow_);
	}
	if (this.oldArrow_) {
		this.map_.removeOverlay(this.oldArrow_);
	}
	this.arrowDisplayed_ = false;
};

/* Pans the map to the parent marker. */
Pointer.prototype.panToMarker_ = function() {
	this.map_.panTo(this.marker_.getLatLng());
};

/* This applies a counter-clockwise rotation to any point. */
Pointer.prototype.getRotatedPoint_ = function(x, y, ang, xoffset, yoffset) {
	var newx = y * Math.sin(ang) - x * Math.cos(ang) + xoffset;
	var newy = x * Math.sin(ang) + y * Math.cos(ang) + yoffset;
	var rotatedPoint = new GPoint(newx, newy);
	return (rotatedPoint);
};