    var mapStatus = {};
    var map;
    var mapHandlers = {};
    var mapData = {};
    var mapCache = {};
    var mapObjects = {};
    var objects = [];
    
    var mapCenters = {residential:[37.2685,55.7456], abroad:[11.9971,44.0876], commercial:[37.2685,55.7456], city:[37.6227,55.7553]};
    var mapScales = {residential:13, abroad:5, city:11, commercial:6};
    
    var controlsOpenOnLoad = {residential:['highway'], abroad:['country']};
    
    var mapControls = {
	toolbar:
		{
		position: 'bottom_left',
		padding: '5,10',
		opacity: 0.9,
		width: 130,
		height: 40
		},
	highway:
		{
		position: 'bottom_right',
		opacity: 0.5,
		width: 200,
		height: 420,
		header: 30,
		window: 1
		},
	country:
		{
		position: 'bottom_right',
		opacity: 0.5,
		width: 200,
		height: 420,
		window: 1
		}, 
	regionSearch:
		{
		select: function() {
			map.closeInfoWindow();
			showMapShadow();
			setHandler('regionSearch',['mousedown','mouseup','mousemove']);
			hideHint();
			},
		unselect: function() {
			setHandler('regionSearch',['mousedown','mouseup','mousemove']);
			hideEl('shadowMap');
			hideHint();
			if (mapCache.type == 'abroad') showAllTabItems('map_country');
			else if (mapCache.type == 'residential') showAllTabItems('map_highway');
			else showAllTabItems();
			}
		}
	};
	
	
    
    function setHandler(name,evts) {
	var events;
	if (typeof(evts) == 'string') events.push(evts);
	else events = evts;
	
	for (var i in events) {
		var evt = events[i];
		var handler = name+'_'+evt;
		if(mapHandlers[handler]) {
			GEvent.removeListener(mapHandlers[handler]);
			mapHandlers[handler] = '';
		} else {
			if (name == 'regionSearch') {
				
				var wSize = getWindowParams();
				
				mapHandlers[handler] = GEvent.addDomListener(getEl('shadowMap'), 'mousedown', function(e) {
					var event = event || e;
					mapData.fromX = event.offsetX ? event.offsetX : event.pageX - wSize.scrollLeft;
					mapData.fromY= event.offsetY ? event.offsetY : event.pageY - wSize.scrollTop;
					mapData.mouseStatus = 1;
				});
				
				mapHandlers[handler] = GEvent.addDomListener(getEl('shadowMap'), 'mouseup', function(e) {
					var event = event || e;
					mapData.mouseStatus = 0;
					searchMapRegion();
				});
				
				mapHandlers[handler] = GEvent.addDomListener(getEl('shadowMap'), 'mousemove', function(e) {
					if (mapData.mouseStatus) {
						var event = event || e;
						mapData.toX = event.offsetX ? event.offsetX : event.pageX - wSize.scrollLeft;
						mapData.toY = event.offsetY ? event.offsetY : event.pageY - wSize.scrollTop;
						drawPolygon();
					}
				});
			}
		}
	}
    }
    

    function drawPolygon() {
	var left = mapData.fromX > mapData.toX ? mapData.toX : mapData.fromX;
	var top = mapData.fromY < mapData.toY ? mapData.fromY : mapData.toY;
	var width = mapData.fromX > mapData.toX ? (mapData.fromX - mapData.toX) : (mapData.toX - mapData.fromX);
	var height = mapData.fromY > mapData.toY ? (mapData.fromY - mapData.toY) : (mapData.toY - mapData.fromY);
		
	showSelection({width:width + 'px',height:height + 'px',top:top + 'px',left:left + 'px'});
    }
    
    function showSelection(data) {
	if (getEl('selection')) {
		showEl('selection');
		setStyle(getEl('selection'), {top:data.top,left:data.left, width: data.width, height:data.height});
	} else {    
		var params = {position:'absolute',backgroundColor:'white',zIndex:10000, border:'2px dotted blue'};
		for (var i in params) params[i] = data[i] || params[i];
		var div = document.createElement("div");
		div.id = 'selection';
		setOpacity(div, 0.5);
		setStyle(div, params);
		setStyle(div, {top:data.top,left:data.left, width: data.width, height:data.height});
		
		document.body.appendChild(div);
	}
    }
    
    function searchMapRegion() {
	if (getEl('selection')) hideEl('selection');
	
	var tab = mapCache.type == 'residential' ? 'highway' : mapCache.type == 'abroad' ? 'country' : ''; 
	if (tab) selectAllTabItems('map_'+tab, false);
	
	var sX = mapData.fromX > mapData.toX ? mapData.toX : mapData.fromX;
	var nX = mapData.fromX > mapData.toX ? mapData.fromX : mapData.toX;
	var sY = mapData.fromY < mapData.toY ? mapData.toY : mapData.fromY;
	var nY = mapData.fromY < mapData.toY ? mapData.fromY : mapData.toY;
	var sw = map.fromContainerPixelToLatLng(new GPoint(sX,sY));
	var ne = map.fromContainerPixelToLatLng(new GPoint(nX,nY));
	
	var bounds = new GLatLngBounds(sw, ne);
	var selectedObjects = [];
	for (var i in objects) {
		var obj = objects[i];
		var isIn = bounds.containsLatLng(obj.getLatLng());
		if (isIn) {
		    obj.show();
		    selectedObjects.push(obj.id);
		}
		else obj.hide();
	}
	var points = selectedObjects.join(',');

	var url = '/cgi-bin/r/bg/search_map.cgi';
	var params = "type=" + mapCache.type + "&objects=" + points;
	ajaxRequest(url, params, 1, 1);
    }
    
    function showMapShadow() {
	var wSize = getWindowParams();
	if (getEl('shadowMap')) {
		var el = getEl('shadowMap');
		el.style.width = wSize.width + 'px';
		el.style.height = wSize.height + 'px';
		el.style.top = wSize.scrollTop + 'px';
		el.style.left = wSize.scrollLeft + 'px';
		showEl('shadowMap');
	}
	else {
		var div = document.createElement("div");
		div.id = 'shadowMap';
		setOpacity(div, 0);
		setStyle(div, {position:'absolute',zIndex:10001,background:'black'});
		div.style.width = wSize.width + 'px';
		div.style.height = wSize.height + 'px';
		div.style.top = wSize.scrollTop + 'px';
		div.style.left = wSize.scrollLeft + 'px';
		document.body.appendChild(div);
	}
    }
    
    window.onresize = correctMapPosition;
    
    function correctMapPosition() {
	var wSize = getWindowParams();
	if (mapStatus.map) {
		styleEl('fullGMap').width = wSize.width + 'px';
		styleEl('fullGMap').height = wSize.height + 'px';
	}
	if (getEl('shadowMap')) {
		styleEl('shadowMap').width = wSize.width + 'px';
		styleEl('shadowMap').height = wSize.height + 'px';
	}
	for (var i in mapControls) if(mapStatus[i] && mapControls[i].window) drawMapControl(i);
    }
    
    function showMapControls(name) {
	var m = [];
	if (typeof(name) == 'string') m.push(name);
	else m = name;
	for (var i in m) {
		mapStatus[m[i]] = 1;
		drawMapControl(m[i]);
		setOpacity(m[i] + 'Map', mapControls[m[i]].opacity);
		showEl(m[i] + 'Map');
	}
    }
    
    function hideMapControls(name) {
	var m = [];
	if (typeof(name) == 'string') m.push(name);
	else m = name;
	for (var i in m) {
		mapStatus[m[i]] = 0;
		hideEl(m[i] + 'Map');
	}
    }
    

    function drawMapControl(name) {
	var ctrl = mapControls[name];
	var wSize = getWindowParams();
	var el = styleEl(name+'Map');
	var offset = ctrl.padding ? ctrl.padding.split(',') : [0,0];
	el.width = ctrl.width + 'px';
	el.height = ctrl.height + 'px';
	
	if (ctrl.header && getEl(name+'MapContent')) {
	    var inel = styleEl(name+'MapContent');
	    inel.height = ctrl.height - ctrl.header + 'px';
	}
	
	if (ctrl.position == 'bottom_left') {
		el.top = wSize.scrollTop + wSize.height - ctrl.height - offset[0] + 'px';
		el.left = wSize.scrollLeft + offset[1] + 'px';
	}  else if (ctrl.position == 'bottom_right') {
		el.top = wSize.scrollTop + wSize.height - ctrl.height - offset[0] + 'px';
		el.left = wSize.scrollLeft + wSize.width - ctrl.width - offset[1] + 'px';
	} else if (ctrl.position == 'top_left') {
		el.top = wSize.scrollTop + offset[0] + 'px';
		el.left = wSize.scrollLeft + offset[1] + 'px';
	}  else if (ctrl.position == 'top_right') {
		el.top = wSize.scrollTop + offset[0] + 'px';
		el.left = wSize.scrollLeft + wSize.width - ctrl.width - offset[1] + 'px';
	}
    }
    
    function toolbarMapCheck(name) {
	var m = [];
	if (typeof(name) == 'string') m.push(name);
	else m = name;
	for (var i in m) {
		var name = m[i];
		var el = getEl('tb_'+name+'Map');
		if (mapStatus[name]) {
			mapStatus[name] = 0;
			el.src = '/i/icons/map/'+name+'.png';
			if (mapControls[name].window) hideMapControls(name);
			if (mapControls[name].unselect) mapControls[name].unselect();
		} else {
			mapStatus[name] = 1;
			el.src = '/i/icons/map/'+name+'_on.png';
			if (mapControls[name].window) showMapControls(name);
			if (mapControls[name].select) mapControls[name].select();
		}
	}
    }
    
    
    function showAllTabItems(id) {
	selectAllTabItems(id, true);
	for (var i in objects) objects[i].show();
    }
    
    function hideAllTabItems(id) {
	selectAllTabItems(id, false);
	for (var i in objects) objects[i].hide();
    }
    
    function selectAllTabItems(id, select) {
	var boxes = document.getElementsByTagName('input');
	var reg = new RegExp("^"+id+"_");
	for (var i in boxes) if (reg.test(boxes[i].id)) boxes[i].checked = select;
    }
    
    
    function fullMapInit(data) {
	var data = data || {};
	
	data.type = data.type || 'residential';
	
	var form = document.forms[0] ? document.forms[0] : '';
		
	if (mapCache.type != data.type) {
	    mapStatus = {};
	    if (mapCache.newObject) {
		mapCache.newObject = 0;
		mapObjects[mapCache.type].pop();
	    }
	}
	mapCache.type = data.type;
	
	mapData.center = mapCenters[data.type];
	var mapScale = mapScales[data.type];
	
	mapStatus.map = 1;
	if (getEl('page_content')) hideEl('page_content');
	
	var wSize = getWindowParams();
	styleEl('fullGMap').width = wSize.width + 'px';
	styleEl('fullGMap').height = wSize.height + 'px';
	styleEl('fullGMap').top = wSize.scrollTop + 'px';
	styleEl('fullGMap').left = wSize.scrollLeft + 'px';
	document.body.style.overflow='hidden';
	styleEl('fullGMap').zIndex = 10000;
	showEl('fullGMap');
		

    	map = new GMap2(document.getElementById('fullGMap'));
	
	map.addControl(new GLargeMapControl());
	var topRight = new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(50,5)); 
	map.addControl(new GMapTypeControl(), topRight);
	map.addControl(new CloseMap());
	map.enableScrollWheelZoom();
	
	if (data.id == 'new' && !mapCache.newObject) {
	    mapCache.newObject = 1;
	    var obj = {id:'new',name:form.name.value};
	    obj.gcoord = mapData.center.join(',');
	    mapObjects[data.type].push(obj);
	}
	else if (data.id == 'new' && mapCache.newObject) {
	    var obj = {id:'new',name:form.name.value};
	    obj.gcoord = form.yamap.value || mapData.center.join(',');
	    mapObjects[data.type].pop();
	    mapObjects[data.type].push(obj);
	}	
	
	for (var i in mapObjects[data.type]) drawMapPoint(mapObjects[data.type][i],data);
	
	map.setCenter(new GLatLng(mapData.center[1],mapData.center[0]), mapScale);
	
		
	if (!data.edit || data.edit && (data.type == 'abroad' || data.type == 'residential')) showMapControls('toolbar');
		
	if(data.noControls) controlsOpenOnLoad = {};
	for (var i in controlsOpenOnLoad[data.type]) mapStatus[controlsOpenOnLoad[data.type][i]] = 1;
	for (var i in mapStatus) if (mapStatus[i] && i != 'map' && i != 'toolbar') {
		mapStatus[i] = 0;
		toolbarMapCheck(i);
	}

	getEl('toolbarMap').onclick = function(e) {
	    var src = document.all ? event.srcElement : e.target;
	    var etype = document.all ? event.type : e.type;
	    if(/^tb_/.test(src.id)) {
		    var name = src.id.match(/tb_(.+)Map$/)[1];
		    toolbarMapCheck(name);
	    }
	}
    
	if (data.type == 'residential') {
	    getEl('highwayMap').onclick = function(e) {
		var src = document.all ? event.srcElement : e.target;
		var etype = document.all ? event.type : e.type;
		if(/^map_highway_/.test(src.id)) {
			var id_highway = src.id.match(/way_(\d+)/)[1];
			var checkStatus = src.checked;
			for (var i in objects) {
				var el = objects[i];
				if(el.id_highway == id_highway) checkStatus ? el.show() : el.hide();
			}
		}
	    }
	}
	if (data.type == 'abroad') {
	    getEl('countryMap').onclick = function(e) {
		var src = document.all ? event.srcElement : e.target;
		var etype = document.all ? event.type : e.type;
		if(/^map_country_/.test(src.id)) {
			var id_country = src.id.match(/country_(\d+)/)[1];
			var checkStatus = src.checked;
			for (var i in objects) {
				var el = objects[i];
				if(el.id_country == id_country) checkStatus ? el.show() : el.hide();
			}
		}
	    }
	}

	if (!data.edit) {
	    var customKML = "http://maps.google.ru/maps/ms?hl=ru&ie=UTF8&msa=0&msid=101568693050853797830.000490fd569b219c0b9f6&output=kml";
	    var kml = new GGeoXml(customKML);
	    map.addOverlay(kml);
	}
    }
    
    function drawMapPoint(el,data) {
	var coord = el.gcoord.split(',');
	var point = new GLatLng(coord[1],coord[0]);
	var params = {title: el.name};
	params.icon = newIcon();
	
	if (data.edit) {
	    if(data.id) {
		if(data.id == el.id) {
		    params.icon = newIcon('red');
		    params.draggable = true;
		    if (coord[0]) mapData.center = [coord[0],coord[1]];
		    point = new GLatLng(mapData.center[1],mapData.center[0]);
		}
	    }
	    else params.draggable = true;
	}
	
	var marker = new GMarker(point, params);
	marker.id = el.id;
	if (el.id_highway) marker.id_highway = el.id_highway;
	if (el.id_country) marker.id_country = el.id_country;
	
	var div = document.createElement("div");
	div.innerHTML = el.html;
	
	if (data.edit) {
	    GEvent.addListener(marker, "dragend", function(l) {
		var coord = l.lng() + ',' + l.lat();
		var params = "yamap=" + coord + "&id=" + marker.id + "&type=" + mapCache.type;
		
		if (data.id == 'new') document.forms[0].yamap.value = coord;
		else ajaxRequest('/cgi-bin/r/bg/edit_map.cgi', params, 1);
	    });
	} else {
	    GEvent.addListener(marker, 'mouseover', function() {
		map.openInfoWindow(point, div);
	    });
	}
	
	objects.push(marker);
	map.addOverlay(marker);
    }
    
    function newIcon(color) {
	var icon = new GIcon(G_DEFAULT_ICON);
	icon.iconSize = new GSize(32, 32);
	icon.image = color == 'red' ? "/i/icons/map/home_red.png" : "/i/icons/map/home.png";
	icon.shadow = "";
	return icon;
    }
    
    function CloseMap() {};
    CloseMap.prototype = new GControl();

    CloseMap.prototype.initialize = function(map) {
        var img = document.createElement("img");
	img.title = 'Закрыть';
        this.imgStyle(img);
        GEvent.addDomListener(img, "click", function() {
		mapData = {};
		document.body.style.overflow='auto';
		for (var i in mapControls) if(getEl(i+'Map')) hideEl(i+'Map');
		hideEl('fullGMap');
		if(getEl('page_content')) showEl('page_content');
		GUnload();
        });
        map.getContainer().appendChild(img);
	return img;
    }

    CloseMap.prototype.getDefaultPosition = function() {
        return new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(2, 2));
    }

    CloseMap.prototype.imgStyle = function(button) {
	button.style.width = "24px";
	button.style.height = "24px";
        button.src = "/i/icons/map/close.jpg";
	button.style.cursor = "pointer";
    }

