
function viMarkerManager(map) {
	var me = this;
	
	me.map_ = map;
	GEvent.bind(me.map_, "moveend", me, me.refreshMove);
	GEvent.bind(me.map_, "zoomend", me, me.refreshZoom);
	GEvent.bind(me.map_, "addoverlay", me, me.addOverlay);
	GEvent.bind(me.map_, "removeoverlay", me, me.removeOverlay);
	
	me.maxMarkerWidth = 1;
	me.maxMarkerHeight = 1;
	
	me.markerSpace = 1.6;
	
	me.previousZoomLevel = false;
	me.lastZoomLevel = me.map_.getZoom();
	
	me.allMarkers = {};
	me.hMarkers = {};
	me.sMarkers = {};
	me.dMarkers = {};
	me.lsMarkers = {};
	me.dAreas = {};
}

viMarkerManager.prototype.addOverlay = function (marker) {
	var me = this,
			tmpMarkers = {};
	
	if(!marker) return false;
	
	mkID = marker.getLatLng().toUrlValue();
	
	if(mkID && !me.dMarkers[mkID] && me.allMarkers[mkID]) {
		me.dMarkers[mkID] = marker;
	}
	
	if(mkID && !me.sMarkers[mkID] && me.allMarkers[mkID]) {
		me.sMarkers[mkID] = marker;
	}
	
	if(me.hMarkers[mkID]) {
		delete me.hMarkers[mkID];
		
		if(me.hMarkers[mkID]) {
			for(var i in me.hMarkers) {
				if(mkID != i)	tmpMarkers[i] = me.hMarkers[i];
			}
		
			me.hMarkers = tmpMarkers;
		}
	}
}

viMarkerManager.prototype.removeOverlay = function (marker) {
	var me = this,
			tmpDMarkers = {};
	
	if(!marker) return false;
	
	mkID = marker.getLatLng().toUrlValue();
	
	delete marker;
	if(me.dMarkers[mkID])delete me.dMarkers[mkID];
	
	if(me.dMarkers[mkID]) {
		for(var i in me.dMarkers) {
			if(mkID != i)	tmpDMarkers[i] = me.dMarkers[i];
		}
	
		me.dMarkers = tmpDMarkers;
	}
}

viMarkerManager.prototype.clo_ = viMarkerManager.prototype.clearLevelOverlay = function () {
	var me = this,
			zoomLevel = me.map_.getZoom(),
			toRemove = new Array();
	
	for(var i in me.dMarkers) {
		if(!me.lsMarkers[zoomLevel] || !me.lsMarkers[zoomLevel][i])
			toRemove.push(i);
	}
	
	for(var i = 0; i < toRemove.length; i++) {
		me.map_.removeOverlay(me.dMarkers[toRemove[i]]);
	}
}

viMarkerManager.prototype.addMarker = function (marker) {
	var me = this;
	
	if(!marker) return false;
	
	mkID = marker.getLatLng().toUrlValue();
	
	if(mkID && !me.allMarkers[mkID]) {
		me.maxMarkerWidth = me.maxMarkerWidth < marker.getIcon().iconSize.width ? marker.getIcon().iconSize.width : me.maxMarkerWidth;
		me.maxMarkerHeight = me.maxMarkerHeight < marker.getIcon().iconSize.height ? marker.getIcon().iconSize.height : me.maxMarkerHeight;
		marker.show();
		me.hMarkers[mkID] = me.allMarkers[mkID] = marker;
	}
}

viMarkerManager.prototype.loadArea = function () {
	var me = this,
			url,
			bb = me.map_.getBounds(),
			urls = self.location.pathname.toString().replace(new RegExp("/[^/]*$", 'gi'), '/').split('/');
	
	for(var a in urls) {
		urls[a] = encodeURI(urls[a]);
	}
	
	url  = self.location.protocol+'//'+self.location.hostname+urls.join('/');
	url += 'bb='+bb.getSouthWest().toUrlValue()+','+bb.getNorthEast().toUrlValue()+'&format=json';
	
	Request.sendPOST(url, null, function (response) {
		if(!response || !response.responseText || response.responseText.match(/<!DOC/))
			return false;

		var cIcon = new GIcon(G_DEFAULT_ICON);
		cIcon.image = '/i/icons/currencyexchange.png';
		cIcon.shadow = '';
		cIcon.iconSize = new GSize(32, 37);
		
		if(typeof(JSON) == 'undefined') {
			eval('var coords = '+response.responseText);
		}else{
			var coords = JSON.parse(response.responseText);
		}
		
		var cMarkerClickMethod = function (mLatLng) {
			var mLat = mLatLng.lat(),
					mLng = mLatLng.lng();

			me.map_.setZoom(me.map_.getBoundsZoomLevel(
				new GLatLngBounds(
					new GLatLng(
						mLat-me.cellWidth_*me.markerSpace,
						mLng-me.cellHeight_*me.markerSpace),
					new GLatLng(
						mLat+me.cellWidth_*me.markerSpace,
						mLng+me.cellHeight_*me.markerSpace)
					)
				)
			);

			me.map_.panTo(mLatLng);
		}
		
		for(var i in coords) {
			mkID = parseFloat(coords[i]['lat']).toFixed(6)+','+parseFloat(coords[i]['lng']).toFixed(6);

			if(!me.allMarkers[mkID]) {
				var cMarker =  new GMarker(
					new GLatLng(coords[i]['lat'], coords[i]['lng']),
					{ title: phrases['exch_point'],
						draggable: false,
						icon: cIcon }
				);
				GEvent.addListener(cMarker, "click", cMarkerClickMethod);
				me.addMarker(cMarker);
			}
		}
		
		me.addLoadedArea(bb);
		me.refreshMove();
	});
}

viMarkerManager.prototype.areaLoaded = function (bounds) {
	var me = this;
	for(var a in me.dAreas) {
		if(me.dAreas[a].containsBounds(bounds)) {
			return true;
		}
	}

	return false;
}

viMarkerManager.prototype.addLoadedArea = function (bounds) {
	var me = this;
	var tmpDAreas = {},
			lbbID = bounds.getSouthWest().toUrlValue()+','+bounds.getNorthEast().toUrlValue();
	
	tmpDAreas[lbbID] = bounds;
	for(var a in me.dAreas) {
		if(!bounds.containsBounds(me.dAreas[a])) tmpDAreas[a] = me.dAreas[a];
	}
	
	me.dAreas = tmpDAreas;
}

viMarkerManager.prototype.shm_ = viMarkerManager.prototype.showAreaMarker = function (abb, mScope) {
	var me = this;
	var areaMarkers = {}, rndArr = new Array(), lat, lng, zoomLevel = me.map_.getZoom(), rnd, mkID, mShown = false;
	
	for(var m in mScope) {
		lat = mScope[m].getLatLng().lat();
		lng = mScope[m].getLatLng().lng();
		
		/*if(abb.aMinX <= lat && abb.aMaxX >= lat && abb.aMinY <= lng && abb.aMaxY >= lng)
			alert(abb.aMinX+' <= '+lat+' && '+abb.aMaxX+' >= '+lat+' = '+(abb.aMinX <= lat && abb.aMaxX >= lat)+'\n'+abb.aMinY+' <= '+lng+' && '+abb.aMaxY+' >= '+lng+' = '+(abb.aMinY <= lng && abb.aMaxY >= lng));*/
		//alert('result: '+ (abb.aMinX <= lat && abb.aMaxX >= lat && abb.aMinY <= lng && abb.aMaxY >= lng));
		
		if(abb.aMinX <= lat && abb.aMaxX >= lat && abb.aMinY <= lng && abb.aMaxY >= lng) {
			mkID = mScope[m].getLatLng().toUrlValue();
			
			//alert(mkID);
			
			if(me.lsMarkers[zoomLevel] && me.lsMarkers[zoomLevel][mkID]) mShown = true;
			
			if(!areaMarkers[mkID] && (mShown || !me.cmo_(mScope[m]))) {
				rndArr.push(mkID);
				areaMarkers[mkID] = mScope[m];
			}
			
			if(me.lsMarkers[zoomLevel] && me.lsMarkers[zoomLevel][mkID] && !me.dMarkers[mkID]) {
				me.map_.addOverlay(mScope[m]);
			}
		}
	}
	
	//if(mShown) alert('length: '+rndArr.length);
	
	if(!mShown && rndArr.length > 0) {
		rnd = rndArr[rndArr.length > 1 ? randomNum(rndArr.length-1) : 0];
		
		if(!me.dMarkers[rnd]) me.map_.addOverlay(areaMarkers[rnd]);
		mkID = areaMarkers[rnd].getLatLng().toUrlValue();
		
		if(!me.lsMarkers[zoomLevel]) me.lsMarkers[zoomLevel] = {};
		me.lsMarkers[zoomLevel][mkID] = areaMarkers[rnd];
	}

	return rndArr.length > 0 ? true : false;
}

viMarkerManager.prototype.cmo_ = viMarkerManager.prototype.checkMarkerOverlaping = function (marker) {
	var me = this,
			zoomLevel = me.map_.getZoom(),
			cw = me.cellWidth_,
			ch = me.cellHeight_,
			ms = me.markerSpace,
			lsm, cLat, cLng,
			mLat = marker.getLatLng().lat(),
			mLng = marker.getLatLng().lng();
	
	if(me.lsMarkers[zoomLevel]) {
		lsm = me.lsMarkers[zoomLevel];
		for(var a in lsm) {
			cLat = lsm[a].getLatLng().lat();
			cLng = lsm[a].getLatLng().lng();
			
			if(cLat-cw*ms <= mLat && cLat+cw*ms >= mLat && cLng-ch*ms <= mLng && cLng+ch*ms >= mLng)
				return true;
		}
	}

	return false;
}

viMarkerManager.prototype.refreshMove = function () {
	var me = this,
			bb = me.map_.getBounds();
	
	if(!me.areaLoaded(bb)) {
		me.loadArea();
		return;
	}
	
	var zl = me.map_.getZoom(),
			lsm = me.lsMarkers,
			dm = me.dMarkers,
			hm = me.hMarkers,
			sm = me.sMarkers,
			gridCols = Math.ceil(me.map_.getSize().width/me.maxMarkerWidth),
			gridRows = Math.ceil(me.map_.getSize().height/me.maxMarkerHeight),
			sw = bb.getSouthWest(),
			ne = bb.getNorthEast(),
			minX = sw.lat(),
			minY = sw.lng();
	
	me.cellWidth_ = (ne.lat()-minX)/gridCols,
	me.cellHeight_ = (ne.lng()-minY)/gridRows;
	
	//alert('total cols: '+ gridCols+'; total rows: '+gridRows+';');

	for(var r = 0; r < gridRows; r++) {
		for(var c = 0; c < gridCols; c++) {
			abb =	{ aMinX: minX+me.cellWidth_*c,
							aMaxX: minX+me.cellWidth_*(c+1),
							aMinY: minY+me.cellHeight_*r,
							aMaxY: minY+me.cellHeight_*(r+1)
						};
			//alert('cell: '+c+'; result: '+(lsm[zl] && me.shm_(abb, lsm[zl]) || dm && me.shm_(abb, dm) || sm && me.shm_(abb, sm) || hm && me.shm_(abb, hm)));
			lsm[zl] && me.shm_(abb, lsm[zl]) || dm && me.shm_(abb, dm) || sm && me.shm_(abb, sm) || hm && me.shm_(abb, hm);
		}
	}
	
	//alert('done');
}

viMarkerManager.prototype.refreshZoom = function (oldZoom, newZoom) {
	var me = this;
	
	me.previousZoomLevel = oldZoom != me.previousZoomLevel ? oldZoom : me.previousZoomLevel;
	me.lastZoomLevel = oldZoom;
	
	me.refreshMove();
	me.clo_();
}

