function Init() {
	 minGroupDistance = 8;
	 movieName = "myFlash";
	 inDebug=false;
//	 inDebug = (agent=='testmap');
	 showGroups = true;
	 currentView=GBounds(0,0,0,0);
	 CancelMove = false;
	 FoldZoomLevel = 0;
	 FnewZoomLevel = 0;
	 factors = Array(101138.377393795,
						50569.1886968976,
						25284.5943484488,
						12642.2971742244,
						6321.1485871122,
						3160.5742935561,
						1580.28714677805,
						790.143573389025,
						395.071786694513,
						197.535893347256,
						98.7679466736282,
						49.3839733368141,
						24.691986668407,
						12.3459933342035,
						6.17299666710176,
						3.08649833355088,
						1.54324916677544,
						0.77162458338772);
	FirstAddCall=true;
	
//debug - set indebug at the top of the library
	if (inDebug) debugWin = window.open("", "", "width=500,height=400");

//hook events 
	GEvent.addListener(map, "moveend", moveEnd);
	GEvent.addListener(map, "zoom", Zoom);
	GEvent.addListener(map, "movestart", moveStart);
	GEvent.addListener(map, "move", move);	

// Create the house icons
	icon = new GIcon();
	icon.image = "http://maps.isslservices.co.uk/images/house3d.png";
	icon.iconSize = new GSize(14, 18);
	icon.iconAnchor = new GPoint(0, 0);
	icon.infoWindowAnchor = new GPoint(6, 1);
	iconflat = new GIcon();
	iconflat.image = "http://maps.isslservices.co.uk/images/house3dblue.png";
	iconflat.iconSize = new GSize(14, 18);
	iconflat.iconAnchor = new GPoint(0, 0);
	iconflat.infoWindowAnchor = new GPoint(6, 1);
	icondevelopment = new GIcon();
	icondevelopment.image = "http://maps.isslservices.co.uk/images/development.png";
	icondevelopment.iconSize = new GSize(14, 18);
	icondevelopment.iconAnchor = new GPoint(0, 0);
	icondevelopment.infoWindowAnchor = new GPoint(6, 1); 
	iconcluster = new GIcon();
	iconcluster.image = "http://maps.isslservices.co.uk/images/housesblack.png";
	iconcluster.iconSize = new GSize(14, 18);
	iconcluster.iconAnchor = new GPoint(0, 0);
	iconcluster.infoWindowAnchor = new GPoint(6, 1); 
}

GMap.prototype.addOverlays=function(a){ // still in use but deprecated after google 1.7
        for (i=0;i<a.length;i++) {
			this.addOverlay(a[i]);
			a[i].show();
        }

}; 

function thisMovie(movieName) {
	if (navigator.appName.indexOf ("Microsoft") !=-1) {
		return document.getElementById(movieName);
  	} else {
    	return document[movieName]
  	}  
}

function startFlash() {
	setFlashVar('agent',agent);
	thisMovie('myFlash').TGotoFrame("/", 1);
//	thisMovie('myFlash').Play();
}

function setFlashVar(aVar,Value) {
	thisMovie('myFlash').SetVariable(aVar,Value);
}

function addOverlays(arr) {
	for (i=0;i<arr.length;i++) {	
		map.addOverlay(arr[i]);
	}
}

function ClearLog() {
		if (!inDebug) return;
		debugWin.document.open();
		debugWin.document.write("");


}
function Log(msg) {
		if (!inDebug) return;
		debugWin.document.write(msg);
		debugWin.document.write('<BR>');
		//debugWin.document.close();
}


function replaceAll( str, from, to ) {
    var idx = str.indexOf( from );
    while ( idx > -1 ) {
        str = str.replace( from, to );
        idx = str.indexOf( from );
    }

    return str;
}

function SwitchToList(args) {
	arr = args.split(",");
	minBeds = parseInt(arr[0]);
	maxBeds = parseInt(arr[1]);
	minPrice = parseInt(arr[2]);
	maxPrice = parseInt(arr[3]);
	if (arr[4]=='1'){
		forSale = 1;
		resultstring = saleURL;
	} else {
		forSale = 2
		resultstring = rentURL;
	}
	resultstring = replaceAll(resultstring,"%minbeds",minBeds);
	resultstring = replaceAll(resultstring,"%maxbeds",maxBeds);
	resultstring = replaceAll(resultstring,"%minprice",minPrice);
	resultstring = replaceAll(resultstring,"%maxprice",maxPrice);	
	document.location = resultstring;
}

function setFilter(args) {
	//MM_showHideLayers('loading','','show');
	DestroyGroups();
	arrHouses = null;
	arrHouses = Array();
	arrHouses["groups"] = Array();
	count = 0
	
	if (args == 'devel') {
		for (i=0;i<arrAllHouses.length;i++) {
			if ( (parseInt(arrAllHouses[i][8])==100)) {
				arrHouses.push(arrAllHouses[i]);
			} else {
				if(arrAllHouses[i][3].visible)	showMarker(arrAllHouses[i][3],false);
			}
		}
	BuildGroups();
	drawtimer = window.setTimeout(addHouses, 100);
	return true;
	}
	
	arr = args.split(",");
	minBeds = parseInt(arr[0]);
	maxBeds = parseInt(arr[1]);
	minPrice = parseInt(arr[2]);
	maxPrice = parseInt(arr[3]);
	forSale = (arr[4]=='1');
	for (i=0;i<arrAllHouses.length;i++) {
		if ( (parseInt(arrAllHouses[i][8]==100)) || 
			(arrAllHouses[i][7]==forSale) && (arrAllHouses[i][4]>=minPrice) && ( (maxPrice ==-1) || (arrAllHouses[i][4]<=maxPrice) ) && (arrAllHouses[i][5]>=minBeds) && ( (maxBeds==-1) ||(arrAllHouses[i][5]<=maxBeds)) ) { 
			arrHouses.push(arrAllHouses[i]);			
			count++;
		} else {		
			if(arrAllHouses[i][3].visible)	showMarker(arrAllHouses[i][3],false);
		}
	}
	BuildGroups();
	drawtimer = window.setTimeout(addHouses, 100);
}

function loadHouses(args) { //this is the entry point from flash
	Init();
	MM_showHideLayers('loading','','show')
	FnewZoomLevel = map.getZoomLevel();	
	arrHouses = null;
	arrHouses = Array();
	arrHouses["groups"] = Array();

	//alert(args);	
	// array structure
				//[0] - long, [1]-lat, [2]-houseref, [3]-marker pointer, [4] - price, [5] - beds, [6] - initial visibility,[7]-for sale,[8]-classval01
		arrAllHouses=eval(args);	
		arrAllHouses["groups"] = Array();	
		var i =0;
		for (i=0; i<arrAllHouses.length; ++i) {
			var point = new GPoint(arrAllHouses[i][0],arrAllHouses[i][1]);		
			switch (parseInt(arrAllHouses[i][8])) {
				case 1:
					var marker = new GMarker(point,iconflat);		
					break;
				case 100:
					var marker = new GMarker(point,icondevelopment);		
					break;
				default:	
					var marker = new GMarker(point,icon);		
					break;			
			}			
			marker.visible = false; // if it's showing overlay
			marker.hasOverlay  = false; // if the overlay has been created
			marker.houseref = arrAllHouses[i][2];
			marker.p1 = arrAllHouses[i][8];
			arrAllHouses[i][3] = marker;
			arrAllHouses[i][3].point = point;
			GEvent.addListener(marker, "click", onHouseClick);					
			if (arrAllHouses[i][6]) {
				arrHouses.push(arrAllHouses[i]);
			} 
		}

//	arrHouses = arrAllHouses;
	
	BuildGroups();
	drawtimer = window.setTimeout(addHouses, 100);
}

function onHouseClick(a) {
	if (this.p1==100) {
		window.open('http://www.peterclarke.co.uk/developments.php?siteid='+this.houseref,'Developer','');
		return false;
	}
	html = '<iframe src="http://maps.isslservices.co.uk/ver2/prop.php?houseref='+this.houseref+'&agent='+agent+'" scrolling="no" width="200" height="160" FRAMEBORDER=0 style="border:none"></iframe>';
	this.openInfoWindowHtml(html);
}

function onGroupClick(a) {
	MM_showHideLayers('loading','','show')
	level = FnewZoomLevel-1;
	if (level<0) {
		MM_showHideLayers('loading','','hide')
		return;
	}
	map.centerAndZoom(new GPoint(this.point.x, this.point.y), level);
}

function MarkerToOverlay(marker) {
for(var a=0;a<map.overlays.length;a++){
	if (map.overlays[a] == arrHouses[i][3])  return ;
}

}

function CreateGroup(i,j) {
	var group = new tgroup;					
	group.id = arrHouses["groups"].push(group) - 1;
	//Log('Created Group: '+group.id);
	arrHouses[j][3].groupid = group.id;
	arrHouses[i][3].groupid = group.id;	
	group.minX = Math.min(arrHouses[i][3].point.x,arrHouses[j][3].point.x);
	group.maxX = Math.max(arrHouses[i][3].point.x,arrHouses[j][3].point.x);					
	group.minY = Math.min(arrHouses[i][3].point.y,arrHouses[j][3].point.y);
	group.maxY = Math.max(arrHouses[i][3].point.y,arrHouses[j][3].point.y);					
	//Log('min X'+arrHouses[i][3].point.x+' and ' +arrHouses[j][3].point.x+' = '+ group.minX );	
	//Log('min Y'+arrHouses[i][3].point.y+' and ' +arrHouses[j][3].point.y+' = '+ group.minY );						
	//Log('New group: '+arrHouses[i][4]+' and ' +arrHouses[j][4]);							
	return group	
}

function DestroyGroups() {
	for (i=0; i<arrHouses["groups"].length; ++i) {	
		map.removeOverlay(arrHouses["groups"][i].marker);					
		GEvent.removeListener(arrHouses["groups"][i].marker.listener);		
	}
	arrHouses["groups"] = null;
	arrHouses["groups"]=Array();

}
function BuildGroups () {	
	Log('Building groups');
	
	DestroyGroups();
	var zoom = map.getZoomLevel();	

	var view = map.getBoundsLatLng();
	a = (view.maxY - view.minY);//* Math.pow(2, (17-zoom));
	for (i=0;i<arrHouses.length;++i) {	// init grouping
		arrHouses[i][3].groupid=-1;
/*		if ( (i>0) && (arrHouses[i-1][3].point.x==arrHouses[i][3].point.x) && (zoom<2)) // on last zoom split houses with same postcode 
		{
//			arrHouses[i-1][3].posX -=5; 
			arrHouses[i][3].point.x +=0.0001; 
		} 		*/
		arrHouses[i][3].posX = arrHouses[i][3].point.x * factors[zoom]; // pixel coordinates from longitude
		arrHouses[i][3].posY = arrHouses[i][3].point.y * Math.pow(2, (17-zoom)); // pixel coordinates form latitude
	}
	
	var tloops=0; var breakedloops=0;
	for (i=0;i<arrHouses.length;++i) {
	//Log('check:'+i);
	if (arrHouses[i][3].groupid>-1) continue // if already in a group		
			for (c=-1; c<2; c=c+2 ) {
				j=i+c;
				if (j<0 || j>arrHouses.length-1) continue; //reach bounderies
				if (arrHouses[i][3].groupid>-1) continue // if already in a group - joined in previously om the loop
				//Log(j);	
				while (Math.abs(arrHouses[i][3].posX - arrHouses[j][3].posX) < minGroupDistance)
				{
					if (Math.abs(arrHouses[i][3].posY - arrHouses[j][3].posY) < minGroupDistance)  
					{ //if close enough to other house																			
						if (arrHouses[j][3].groupid==-1) {  // the matching house doesn't belong to a group create one and join both to it
							CreateGroup(i,j);					
						} else { // if mathing house belongs to a group then join the house to that group
							arrHouses[i][3].groupid = arrHouses[j][3].groupid;
							arrHouses["groups"][arrHouses[j][3].groupid].minX = Math.min(arrHouses[i][3].point.x,arrHouses["groups"][arrHouses[j][3].groupid].minX);
							//Log('GID = '+arrHouses[j][3].groupid);
							//Log('min '+arrHouses[i][3].point.x+' and ' +arrHouses["groups"][arrHouses[j][3].groupid].minX+' = '+ arrHouses["groups"][arrHouses[j][3].groupid].minX );
							//Log('Joining  '+arrHouses[i][4]+':'+i+ 'to ' + arrHouses[j][4]+':'+j);					
							arrHouses["groups"][arrHouses[j][3].groupid].maxX = Math.max(arrHouses[i][3].point.x,arrHouses["groups"][arrHouses[j][3].groupid].maxX);					
							arrHouses["groups"][arrHouses[j][3].groupid].minY = Math.min(arrHouses[i][3].point.y,arrHouses["groups"][arrHouses[j][3].groupid].minY);
							arrHouses["groups"][arrHouses[j][3].groupid].maxY = Math.max(arrHouses[i][3].point.y,arrHouses["groups"][arrHouses[j][3].groupid].maxY);					
						}		
					break;  //house formed a group with the overlaping house or joined it's group				
					}
				j=j+c;	
				if (j<0 || j>arrHouses.length-1) break; //reach boundries					
				} 						  	
			}	
	}
	Log('loops:'+tloops+' breaked '+breakedloops);
	createGroupsOverlay();
}

function createGroupsOverlay () {
	//create group markers
	Log('Groups count:');
	Log(arrHouses["groups"].length);
	var arrGroups  = Array();		
	for (i=0; i<arrHouses["groups"].length; ++i) {
		GX	= (arrHouses["groups"][i].maxX+arrHouses["groups"][i].minX)/2;
		GY	= (arrHouses["groups"][i].maxY+arrHouses["groups"][i].minY)/2;
		Log('gx'+GX+' gy'+GY);		
		var point = new GPoint( GX, GY );		
		var marker = new GMarker(point,iconcluster);
		marker.id = i;
		arrHouses["groups"][i].marker = marker;
		arrGroups.push(marker);
		 // Show this marker's index in the info window when it is clicked
		arrHouses["groups"][i].marker.listener = GEvent.addListener(marker, "click", onGroupClick);	
		arrHouses["groups"][i].marker.point = point;
	}	
	map.addOverlays(arrGroups); 
}


function showMarker(marker,show) {
	if (show) {
		marker.show();
	} else {
		marker.hide();	
	}
	marker.visible = show;		
}

function addHouses() {

	Log('AddHouses');
	CancelMove = false;
	var zoom = map.getZoomLevel();	
	var view = map.getBoundsLatLng();
	
	var x=0; var showing=0;
	var arrMarkers = Array();
	for (i=0; i<arrHouses.length; ++i) {		
		//if not in view skip if there is no marker assigned or delete marker if assigned already
		if (arrHouses[i][0] < view.minX || arrHouses[i][0] > view.maxX || arrHouses[i][1] < view.minY || arrHouses[i][1] > view.maxY) {
		//not in view
			//.. but show overlay	
			if (arrHouses[i][3].groupid>-1) { // if in group hide the whole group
				arrHouses["groups"][arrHouses[i][3].groupid].marker.hide(); //??
			}

			if (arrHouses[i][3].visible) { 
				arrHouses[i][3].hide(); 
				arrHouses[i][3].visible = false;
			};
			continue; 
		// in view	
		} else { 
			// in view and do not show overlay
			showing++;
			if (arrHouses[i][3].groupid>-1) { //in group
				arrHouses["groups"][arrHouses[i][3].groupid].marker.show();
				if (arrHouses[i][3].visible) { 
					arrHouses[i][3].hide(); 
					arrHouses[i][3].visible = false;
				}
			} else {						// not in group	
				if (!arrHouses[i][3].visible) { 
					//Log('marker x:'+map.overlays[arrHouses[i][3]]);
					if (!arrHouses[i][3].hasOverlay) {				
						Log(arrHouses[i][3].houseref);
						arrMarkers.push(arrHouses[i][3]);					
						x++;
						//hack to replace the use isObject which still has some problems
						arrHouses[i][3].hasOverlay = true;
					} else {					
						arrHouses[i][3].show(); 	
					}
					arrHouses[i][3].visible = true;				
				} 			
			}
		}

	}
	MM_showHideLayers('loading','','hide')			
	map.addOverlays(arrMarkers);
	setFlashVar('nrploted',arrHouses.length);  
	currentView= view;
}

function moveEnd() {

	CancelMove = true;
	// ignore small movements  0.05 currently
	var bounds = map.getBoundsLatLng();
	var movedY = Math.abs((bounds.minY-currentView.minY) / (currentView.maxY-currentView.minY));
	var movedX = Math.abs((bounds.minX-currentView.minX) / (currentView.maxX-currentView.minX));
	//draw if moved 5% of map
	if (movedX>0.05 || movedY>0.05) 
	{
		MM_showHideLayers('loading','','show')
		drawtimer = window.setTimeout(addHouses, 100);
	}
}

function moveStart() {
	//Log('moveStart');
}

function move() {
	//Log('moveStart');
}

function Zoom(oldZoomLevel, newZoomLevel) {
	if (oldZoomLevel == newZoomLevel) return;
	FoldZoomLevel = oldZoomLevel;
	FnewZoomLevel = newZoomLevel;
	MM_showHideLayers('loading','','show')
	ClearLog();
	//Log('current zoom:' + newZoomLevel+' old zoom:'+oldZoomLevel);	
	BuildGroups();
	// this one triggers moveStart/EBD by default

}



//group of consolidated markers
	function tgroup() {
  		this.minX = 0;
  		this.maxX = 0;  
  		this.minY = 0;  
  		this.maxY = 0; 
  		this.id	= -1; 
		this.marker = false;
	}