var defaultClusterSize = 288;
var minzoom = 7;
var defaultzoom = 13;
var newmap;
var gmap = null; 
function ce(a){return document.createElement(a)};
function ct(a){return document.createTextNode(a)};
function ac(e,c){e.appendChild(c)};
function dg(a){return document.getElementById(a)};

if (typeof sg == "undefined") {
    var sbase = "/vebra";
} else {
    var sbase = "/" + sg;
}


function Hashtable() {this.clear()}
;Hashtable.prototype.clear=function(){this.hashtable={}} 
;Hashtable.prototype.contains=function(k){return(this.hashtable[k]!=null)}
;Hashtable.prototype.read=function(k){return this.hashtable[k]}
;Hashtable.prototype.add=function(k,v){if(k!=null)this.hashtable[k]=v}
;Hashtable.prototype.length=function(){var i=0;for(var x in this.hashtable)i++;return i}
;Function.prototype.method=function(n,f){this.prototype[n]=f;return this};

function PropertyModel () {
	this.id = 0;
	this.lnglat = null;
	this.onmap = false;
	this.marker = null;
	this.displayprice = '';
	this.price = 0;
	this.type = '';
	this.beds = 0;
	this.address = '';
	this.image = '';
	this.details = '';
	this.agent = '';	
}

function Map () {
	this.Created = false;
	this.loaded = false;
	this.icon0 = new GIcon();
	this.MinPrice = -1;
	this.MaxPrice = -1;
	this.Bedrooms = -1;
	this.PlotIndex = 0;
	this.PlotBatch = 15;
	this.PlotInc = 100;
	this.viewcount = 0;
	this.properties = new Hashtable();
	this.clusters = new Hashtable();
	this.ignoredrag = false;
	this.timer = null;
	this.zoom = 13;
	this.currentview = 0;
	this.clearclusters = false;
	this.datarequest = GXmlHttp.create();
	this.state = 0;
	this.cancel = false;
	this.csindex = 0;
}

/* state 
0 = default
1 = clearing
2 = getting data
3 = populating data
4 = plotting
*/

		
Map.method('rnd', function () {
		var chars="abcdefghijklmnopqrstuvwxyz";
		var pass="";
		for(var x=0;x<25;x++)pass+=chars.charAt(Math.floor(Math.random()*25));
		return pass;
});

Map.method('getCommand', function (command) {
    var url = sbase +  "/ajax/init/" + this.rnd();
	var request = GXmlHttp.create();
	request.open("GET", url, true);
	request.onreadystatechange = function() {
		if (request.readyState == 4 && request.responseText) {
			var exe = request.responseText;
			eval(exe);
			delete request;
		}
	}
	request.send(null);
});

Map.method('getShortList', function (command) {
	if ( command ) {
		var url = sbase + "/ajax/shortlist/" + command;
	} else { 
		var url = sbase + "/ajax/shortlist?" + this.rnd();
	}
	var request = GXmlHttp.create();
	request.open("GET", url, true);
	request.onreadystatechange = function() {
		if (request.readyState == 4 && request.responseText) {
			var sl = dg("s-shortlist");
			sl.innerHTML = request.responseText;
			var links = sl.getElementsByTagName("a");
			for ( var i=0; i < links.length; i++) {
				var href = links[i].getAttribute("href");
				if ( href ) {
					if( href.indexOf("remove") != -1 ) {
					  //  x = href.substr(href.lastIndexOf("/")+1);
						links[i].onclick = function(){newmap.getShortList("remove="+this.href.substr(this.href.lastIndexOf("/")+1));return false;};
					}
				}
			}
		}
	}
	request.send(null);
});

Map.method('isCancelled', function () {
	if ( this.cancel ) {
		this.state = 0;
		this.PlotIndex = 0;
		this.cancel = false;
		writeInfo("");
		return true;
	} 
	return false;
});

Map.method('addPropFromXml', function (prop,p,id) {
		prop.count = p.getAttribute("co");
		prop.type = p.getAttribute("t");
		prop.lnglat = new GLatLng(parseFloat(p.getAttribute("y")), parseFloat( p.getAttribute("x") ));
		prop.id = id;
		if (prop.count == "" || prop.count == null) {
			prop.displayprice = p.getAttribute("p");
			prop.price = parseInt(p.getAttribute("pv"));
			if (prop.type == "(Not Specified)") prop.type = "";
			prop.beds = parseInt(p.getAttribute("b"));
			prop.address = p.getAttribute("a");
			prop.image = p.getAttribute("r");
			if (prop.image.length == 0 ) prop.image = "/images/noimage/mapanoimage.gif";
			prop.details = sbase + "/property/" + id;
			prop.agent = p.getAttribute("ag");
		} 			
		return prop;   
});

Map.method('getData', function (initialCall) {
if ( gmap.isLoaded() ) {	
    // clearing
    this.state = 1;	
	    var mb = gmap.getBounds();
		writeInfo("Clearing...");
		var newproperties = new Hashtable();
		for (var key in this.properties.hashtable ) {			
			var currentprop = this.properties.hashtable[key];
			if( !mb.containsLatLng(currentprop.lnglat) || 
						(currentprop.price < this.MinPrice) || 
						((this.MaxPrice > -1 )&&(currentprop.price > this.MaxPrice)) ||
						((this.Bedrooms > -1 )&&(currentprop.beds <= this.Bedrooms)) || (currentprop.type == "cluster" && this.clearclusters)) 
			{
				this.removeProperty(currentprop);
			} else {
				newproperties.add(key,currentprop);
			}
		}
		this.clearclusters = false;
		this.properties.clear();
		this.properties = newproperties;
		writeInfo("Cleared.");
	}
	if ( initialCall ) {
	    window.setTimeout('newmap.getData2(true)',10);
	} else {
	    window.setTimeout('newmap.getData2()',10);	
    }	
});

Map.method('getData2', function (initialCall) {
	
	if ( this.isCancelled() ) return;
    if ( gmap.getZoom() < minzoom )  return;
    var url = sbase + "/ajax/mapdata/";
	if ( gmap.isLoaded() ) {
		var mb = gmap.getBounds();
		var sw = mb.getSouthWest();
		var ne = mb.getNorthEast();	
		var cent = gmap.getCenter();
	}
	if ( !initialCall) {	
		url += "minx=" + sw.lng();
		url += "&maxx=" + ne.lng();
		url += "&miny=" + sw.lat();
		url += "&maxy=" + ne.lat();
		url += "&cenx=" + cent.lng();
		url += "&ceny=" + cent.lat();
		url += "&zoom=" + gmap.getZoom();
	} else {
		url += "rand=" + this.rnd();
	}
	var bounds = new GLatLngBounds();
	if ( this.MinPrice >= 0 ) url += "&lop=" + this.MinPrice;
	if ( this.MaxPrice >= 0 ) url += "&hip=" + this.MaxPrice;
	if ( this.Bedrooms >=0 ) url += "&bed=" + this.Bedrooms;

	if ( this.isCancelled() ) return;
	// getting data
    this.state = 2;
 	// use the global request, we only want one request at a time 
	var request = GXmlHttp.create();
	//this.datarequest.abort();
	request.open("GET", url, true);
	request.onreadystatechange = function() {
		if (request.readyState == 4 && request.responseXML) {
			// getting data
			if ( newmap.isCancelled() ) return;
			newmap.state = 3;
			var xmlDoc = request.responseXML;

			var ep =  xmlDoc.getElementsByTagName("top");
		    newmap.viewcount = parseInt(ep[0].getAttribute("m"));
		    newmap.totalcount = parseInt(ep[0].getAttribute("count"));
		    if ( newmap.viewcount == -1 ) { newmap.noSession(); return; }
		    var pc = 0;
			var props = xmlDoc.documentElement.getElementsByTagName("h");
			for(var i =0; i < props.length; i++){	
				var p = props[i];
				var id = p.getAttribute("id");
				if (!newmap.properties.contains(id)) {
					var prop  = new PropertyModel();
					newmap.properties.add(id,newmap.addPropFromXml(prop,p,id));
					if ( initialCall ) bounds.extend(prop.lnglat);
				}
			}
			pc += props.length;
			props = xmlDoc.documentElement.getElementsByTagName("c");
			pc += props.length;
			for(var i =0; i < props.length; i++){	
				var p = props[i];
				var id = p.getAttribute("id");
				if (!newmap.properties.contains(id)) {
					var prop  = new PropertyModel();
					var cprops = p.getElementsByTagName("h");
					if ( cprops.length > 0 ) prop.clusterpropids = [];
					for(var j =0; j < cprops.length; j++){	
							var cp = cprops[j];
							prop.clusterpropids.push(cp.getAttribute("id"));
					}
					newmap.properties.add(id,newmap.addPropFromXml(prop,p,id));
					if ( initialCall ) bounds.extend(prop.lnglat);
				}
			}
			delete request;
			if ( !initialCall ) {
				newmap.addMarkers();
			} else {	
			    if ( pc == 0 ) {
			        // no matches, go to the results
			        window.location.href = sbase + "/property/search/" + dbt;
			    } else {
				    var zoom = gmap.getBoundsZoomLevel(bounds);
				   // if ( zoom < minzoom ) zoom = minzoom;
				    var sw = bounds.getSouthWest();
				    var ne = bounds.getNorthEast();	
				    var lat = (ne.lat() + sw.lat()) /2;
				    var lng = (ne.lng()+ sw.lng()) /2;
				    var center = new GLatLng( lat,lng );
				    gmap.setCenter(center,zoom, G_NORMAL_MAP);				
				    newmap.LoadControls();
				    newmap.addMarkers();
				 }
			}				
		} else {
			switch ( request.readyState ) {
				case 0 : writeInfo("Loading data."); break;
				case 1 : writeInfo("Loading data..."); break;
				case 2 : writeInfo("Preparing data."); break;
				case 3 : writeInfo("Preparing data..."); break;
			}
		}
	}
	request.send(null);
});

Map.method('showPropertyLocation', function(lat, lng, zoom, h) {
    var p = new GLatLng(lat, lng);
    this.ignoredrag = true;
    gmap.setCenter(p, zoom, G_NORMAL_MAP);
    var marker = new GMarker(p, { icon: this.icon0 });
    gmap.addOverlay(marker);
    marker.openInfoWindowHtml(h);
    newmap.LoadControls();
    GEvent.addListener(marker, "click", function() { marker.openInfoWindowHtml(h) });
    writeLeftInfo("");
});

Map.method('addMarkers', function () { 

		writeInfo ("Adding properties...");
		if ( this.isCancelled() ) return;
		var j = this.PlotIndex;
		var plen = this.properties.length();
		var i = 0;
		for (var key in this.properties.hashtable ) {	
			if ( i < j ) continue;
			var currentprop =this.properties.hashtable[key];
			if(!currentprop.onmap){
					this.addMarker(currentprop);
					this.currentview += 1;
			}
			i++;
			if (  j >= (j + this.PlotBatch) ) break;
		}
		this.PlotIndex += this.PlotBatch;
		if (  this.PlotIndex  > plen ) {
			var totals = this.viewcount != this.totalcount ? "" + this.viewcount + " of " + this.totalcount : this.viewcount;
			writeLeftInfo("Showing <em>" + totals + '</em> properties on the map.');
			this.PlotIndex = 0;
			this.state = 0;
			writeInfo("");
			if (!this.loaded) this.onLoaded();
		} else {
			this.timer = window.setTimeout('newmap.addMarkers(false)',this.PlotInc);
		}
});

Map.method('addMarker' , function (p) {
		if (p.type == "cluster" ) {
		    var marker = new GMarker(p.lnglat, { icon: this.icon1, title: this.makeToolTip(p) });			    
		} else {
		    var marker = new GMarker(p.lnglat, { icon: this.icon0, title: this.makeToolTip(p) });
		}
		p.marker = marker;
		p.onmap= true;				
		marker.propid = String(p.id);
		gmap.addOverlay(marker);					
});
 

Map.method('clearAllProperties', function () { 
	if (gmap.isLoaded()) {
		for (var key in this.properties.hashtable ) {	
			this.removeProperty(this.properties.hashtable[key]);
		}
		this.properties.clear();
	}
});


Map.method('removeProperty', function (p) { 
		if (!p) return;
		if ( p.marker) gmap.removeOverlay(p.marker);
		p.marker = null;
		if (p.onmap) this.currentview -= 1;
		p.onmap = false;
		if ( p.mouseoverevent ) GEvent.removeListener(p.mouseoverevent);
		if ( p.mouseoutevent ) GEvent.removeListener(p.mouseoutevent);
		if ( p.shortlistevent ) GEvent.removeListener(p.shortlistevent);	
});


Map.method('noSession', function() { window.location = sbase + "/property/search/" + dbt });

Map.method('showClusteredProps',function(cluster,overlay){

    var url = sbase + "/ajax/property/";
	var cid = cluster.id;
	url += "x=" + cid.substring(1,cid.indexOf("_"));
	url += "&y=" + cid.substring(cid.indexOf("_") + 1, cid.indexOf("-"));
	url += "&z=" + cid.substring(cid.indexOf("-") + 1);
	var request = GXmlHttp.create();
	request.open("GET", url, true);
	request.onreadystatechange = function() {
		if (request.readyState == 4 && request.responseXML) {
			var xmlDoc = request.responseXML;
			var props = xmlDoc.documentElement.getElementsByTagName("h");
			var propsfortabs = [];		
			var l = props.length;
			
			var siz = (l == 2) ? defaultClusterSize : (l * 88);
			var tabs =[];
			for(var i =0; i < l; i++){	
				var p = props[i];
				var id = p.getAttribute("id");
				var prop  = new PropertyModel();
				prop = newmap.addPropFromXml(prop,p,id)				
				tabs.push( new GInfoWindowTab(parseInt(i)+1,newmap.makePopupHtmlDom(prop,siz) ));
            }
            if (l > 0) {
                gmap.openInfoWindowTabs(overlay.getLatLng(), tabs);
            } else {
                gmap.openInfoWindow(overlay.getLatLng(), newmap.makePopupHtmlDom(prop));
            }
			delete request;
		} 
	}
	request.send(null);
});



Map.method('makePopupHtmlDom', function(prop,siz) {

		var gd = ce("div");
		
		    gd.setAttribute("id","gmapcontent");
		    
		    if ( siz ) {
		        if (siz < defaultClusterSize)
		        {
		            siz = defaultClusterSize;
		        }
		            gd.style.width = siz+"px";           
		    }
		    if ( prop.type=="cluster" ) {
			    var h = ce("h1");	
			    ac(h,ct(prop.count + ' properties at this location.'));
			    ac(gd,h);
			    h = ce("h2");
			    ac(h,ct('Please zoom in to see the individual properties.') );
			    ac(gd,h);	
			    return gd;
		    }		
		    var im = ce("img");
			    im.setAttribute("src",prop.image);
			    im.setAttribute("width","84");
			    im.setAttribute("height","63");
			    im.className = "prop";
		    ac(gd,im);
		    var gma = ce("div");
		      gma.className = "gm-address"; 
		    ac(gd,gma);  
		    var h = ce("h2");			
		    ac(gma,h); 
		    ac(h,ct(prop.address));
		    h = ce("h3");
		    ac(gma,h); 	
		    ac(h,ct(prop.displayprice.replace("&#163;",  String.fromCharCode(163))));
		    var gmc = ce("div"); 
		      gmc.className = "gm-content";
		    ac(gd,gmc);
		    var p = ce("p");
		    p.className = "agentname";
		    ac(p,ct(prop.agent));
		    ac(gmc,p);
		    p = ce("p");
		    if ( prop.beds > 0)  { 
			    ac(p,ct(prop.beds + ' Bedroom ' + prop.type));
		    } else {
			    ac(p,ct(prop.type));
		    }	
		    ac(gmc,p);
		    var ul = ce("ul");
		    var li = ce("li")
		    var a = ce("a");
		    a.setAttribute("href",prop.details);
		    a.setAttribute("title","Full details");
		    ac(a,ct("Full details"));
		    ac(li,a);
		    ac(ul,li);
		    li = ce("li");
		    a = ce("a");
		    a.setAttribute("href", sbase + "/property/search/map/add/" + prop.id);
		    a.setAttribute("title","Add to shortlist");
		    ac(a,ct("Add to shortlist"));
		    ac(li,a);
		    ac(ul,li);
		    a.onclick = function () {
			    newmap.getShortList("add="+prop.id);
			    return false;
		    }
		    li = ce("li");
		    a = ce("a");
		    a.setAttribute("href", sbase + "/register/property/" + dbt + "/" + prop.id);
		    a.setAttribute("title","Contact agent");
		    ac(a,ct("Contact agent"));
		    ac(li,a);
		    ac(ul,li);
		    ac(gmc,ul); 
	return gd;
});

Map.method('makeToolTip', function(prop) {
	if (prop.type=="cluster" && prop.clusterpropids) {
		return '' + prop.count + ' properties. click to view.';		
	} else if (prop.type=="cluster"){
		return '' + prop.count + ' properties.';	
	} else {
		return '' + prop.displayprice.replace("&#163;",  String.fromCharCode(163))+ ' ' + prop.address  + '';
	}
});

Map.method('onFinishDrag', function() {
	if ( !this.ignoredrag) {
		if ( gmap.getZoom() >= minzoom ) {
			writeInfo("Waiting...");
			this.abort();
			this.getData(false);
		} else {
			this.clearAllProperties();
			writeLeftInfo("Please zoom in to see properties on the map.");		
		}
	}
});

Map.method('abort', function() {
		if ( this.state > 0 ) {
			this.cancel = true;
			this.PlotIndex = 0;
			if ( this.state == 2 ) {
			
			} else if ( this.timer ) {
				window.clearTimeout(this.timer);
			}
			writeInfo("");
			this.state = 0;
		}
});


Map.method('onZoom', function() {
	if ( !this.ignoredrag) {
		gmap.closeInfoWindow();
		if ( gmap.getZoom() >= minzoom) {
			if ( this.zoom > gmap.getZoom()) this.clearAllProperties();
			this.clearclusters = true;
			this.getData(false);	
		} else if (gmap.getZoom() < minzoom) {
			this.abort();
			this.clearAllProperties();
			writeLeftInfo("Please zoom in to see properties on the map.");		
		}
	}
	this.zoom = gmap.getZoom();
});


Map.method('onClick', function(overlay, point) {
		if (overlay != null && overlay.propid) {
			var prop = this.properties.hashtable[overlay.propid];
			if ( prop.clusterpropids ) {
			    this.showNextCluster(prop.clusterpropids,0,overlay);
			} else if (prop.type=="cluster" && prop.count <= 5 ) {
				this.showClusteredProps(prop,overlay);
			} else {
			    gmap.openInfoWindow(overlay.getLatLng(), this.makePopupHtmlDom(prop));
			}
		}
});

Map.method('showNextCluster', function(parray,sindex,overlay) {
    gmap.closeInfoWindow();
	var tabs =[];
	var ntabs = 4;
	var l =  parray.length;
	var remain = l - sindex;
    var siz = (remain <= 2) ? 264 : (remain * 88);
    if ( remain  > ntabs ) {
        siz = (ntabs+1) * 88;   
    } 
    for ( var i=sindex; (i < l) && (i < ntabs+sindex);i++) {
        var p = this.properties.hashtable[parray[i]];
        tabs.push( new GInfoWindowTab(parseInt(i)+1,this.makePopupHtmlDom(p,siz) ));
    }
    if ( remain > ntabs ) {
  	    var gd = ce("div");
            gd.setAttribute("id","gmapcontent");
        gd.style.width = siz+"px";
        var h = ce("h1");
        ac(h,ct(l + ' properties at this location.'));
        ac(gd,h);		  
        var ul = ce("ul");	
        var li = ce("li")
        var a = ce("a");
        a.setAttribute("href","#");
        a.onclick = function () {
            newmap.showNextCluster(parray,sindex + ntabs,overlay);
            return false;
        }
        var nx = remain - ntabs;
        if(l > ntabs) l = ntabs; 
        ac(a,ct("Next " +nx + " properties..." ));
        ac(li,a);
        ac(ul,li);
        ac(gd,ul);
        tabs.push( new GInfoWindowTab("More", gd));
    }
    overlay.openInfoWindowTabs(tabs );
});
			    
			    
			    
Map.method('makePopupHtmlForManyPropsDom', function(p) {

	var gd = ce("div");
		gd.setAttribute("id","gmapcontent");
	var h = ce("h1");	
		ac(h,ct(p.length + ' properties at this location.'));
		ac(gd,h);		    
	var ul = ce("ul");	
	for ( var i=0; i < p.length;i++) {
	    var prop = this.properties.hashtable[p[i]];

	    var li = ce("li")
	    var a = ce("a");
	    a.setAttribute("href",prop.details);
	    a.setAttribute("title","Full details");
	    ac(a,ct(prop.address));
	    ac(li,a);
	    ac(ul,li);
    }
	ac(gd,ul);
	return gd;
});


Map.method('onLoaded', function() {

		GEvent.bind(gmap, "click",	this,	this.onClick);	
		GEvent.bind(gmap, "moveend", this, this.onFinishDrag);
		GEvent.bind(gmap, "zoomend", this, this.onZoom);
		this.loaded = true;
});

Map.method('LoadControls', function() {
		gmap.addControl(new GSmallMapControl());
		gmap.addControl(new GMapTypeControl());
		gmap.addControl(new GScaleControl());
		gmap.addControl(new GOverviewMapControl());	
});


Map.method('Create', function () { 
	if(!this.Created){
		if (!GBrowserIsCompatible()) {
			/// TODO :load image instead
			return;
		}
		this.Created = true;
		this.icon0.image = "/images/map/icon6.png";
	    this.icon0.shadow = "/images/map/map_shadow1.png";
		this.icon0.iconSize = new GSize(15, 15);
		this.icon0.shadowSize = new GSize(17, 17);
		this.icon0.iconAnchor = new GPoint(7, 7);
		this.icon0.infoWindowAnchor = new GPoint(15, 0);
		this.icon1 = new GIcon(this.icon0);
		this.icon1.image = "/images/map/map_icon_multi2.png";
		this.getCommand("init");
		this.getShortList();
	}
});

Map.method('QuickSearch', function(e) {
    if (searchterm ) {
      if ( searchterm != dg("geo").value) {
        return true;
      }
    }
	newmap.Bedrooms = parseInt(dg("beds").value);
	newmap.MinPrice = parseInt(dg("lop").value);
	newmap.MaxPrice = parseInt(dg("hip").value);
	if ( gmap.getZoom() >= minzoom) {
		newmap.getData(false);		
	}
	return false;
});

function init () {	
	dg("s-utilbar").innerHTML = "<p id=\"foundtext\">Please wait while the map and properties load.</p><p id=\"mapinfo\"></p>";
    newmap = new Map();
    gmap = new GMap2(dg("resultsmap"));
	newmap.Create();	
    var geo_now = dg("geo");
    if ( geo_now != null ) {
        searchterm = geo_now.value;
    } else {
        searchterm = null;
    }   
	var s=dg("search");	
	if (s)  {
        var ons = s.onsubmit;
        if  (typeof(ons) == "function") {
            s.onsubmit = function() { ons(); return newmap.QuickSearch(); }
        } else { 
            s.onsubmit= newmap.QuickSearch;
        }
	}

}

function writeInfo(v){dg("mapinfo").innerHTML=v;}
function writeLeftInfo(v){dg("foundtext").innerHTML=v;}
;function addLoadEvent(f){ var ono=window.onload; if (typeof window.onload!='function'){window.onload=f;}else{window.onload=function(){ono();f();}}}

addLoadEvent(init);



