function xtext_gmap_insert(textarea){
	var title = $('xtext_gmap_title').get('value');
	var type = $('xtext_gmap_type').get('value');
	var zoom = $('xtext_gmap_zoom').get('value');
	var center = $('xtext_gmap_center').get('value');
	lsPanel.putText(
		textarea,
		'<gmap'
			+(title === '' ? '' : ' title="'+title.h2c()+'"')
			+(type === '' ? '' : ' type="'+type+'"')
			+(zoom === '' ? '' : ' zoom="'+zoom+'"')
			+(center === '' ? '' : ' center="'+center+'"')
		+'>'+xtext_gmap_construct_innertext()+'</gmap>'
	);
	xtext_close_popup('gmap');
}

function xtext_gmap_construct_innertext(){
	var lines = [];
	xtext_gmap_points.each(function(marker){
		if($type(marker) != 'object' || $type(marker.getMap()) != 'object') return;
		var line = [
			xtext_mathround(marker.getPosition().lat(), 7),
			xtext_mathround(marker.getPosition().lng(), 7),
			marker.getTitle()
		];
		lines.push(line.join(';'))
	});
	return lines.join("\r\n");
}

function xtext_gmap_init(panel_rules){
	xtext_add_panel_button(
		panel_rules,
		'xtext_open_popup("gmap")',
		'tag/gmap/gmap-panel-icon.png',
		xtext_lang_get('xtext_gmap_panel_title'),
		'gmap'
	);
}

var xtext_gmap_points = [];

function xtext_popup_gmap_show_after(){
	var opt = window['xtext_gmap_map_preview_opt'];
	var mapopt = $type(opt) == 'object'
		? {
			zoom: parseInt(opt.zoom),
			mapTypeId: opt.type,
			center: new google.maps.LatLng(
				parseFloat(opt.lat),
				parseFloat(opt.lng)
			)
		}
		: {}
	;
	var map = new google.maps.Map($('xtext_gmap_preview'), mapopt);
	$('xtext_gmap_insert').removeEvents('click').addEvent('click', function(){
		$('xtext_gmap_type').set('value', map.getMapTypeId());
		$('xtext_gmap_zoom').set('value', map.getZoom());
		$('xtext_gmap_center').set('value',
			xtext_mathround(map.getCenter().lat(), 7)
			+';'+xtext_mathround(map.getCenter().lng(),7)
		);
		xtext_gmap_insert(opt.textarea);
	});
	var infowindow = new google.maps.InfoWindow({
        content: '<input type="text" id="xtext_gmap_point_title_edit">'
        	+'<div id="xtext_gmap_point_info"></div>'
    });
	
	function add_marker(map, latLng, title, pop_iw){
		var marker = new google.maps.Marker({
			map: map,
			position: latLng,
			title: $type(title) == 'string' ? title : '',
			zIndex: 1,
			visible: true,
			draggable: true
		});
		points.push(marker);
		var index = points.indexOf(marker);
		if(marker.getTitle() === ''){
			marker.setTitle(xtext_lang_get('xtext_gmap_point')+' '+index);
		}
		var option = new Element('option', {
			text: marker.getTitle(),
			value: index
		}).inject($('xtext_gmap_addr_points'));
		google.maps.event.addListener(marker, 'click', function() {
			infowindow.open(map,marker);
			$('xtext_gmap_point_info').set(
				'html',
				xtext_mathround(marker.getPosition().lat(),7)
				+' '+xtext_mathround(marker.getPosition().lng(),7)
			);
			$('xtext_gmap_point_title_edit')
			.set('value',marker.getTitle())
			.set('_index',points.indexOf(marker))
			.removeEvents('keyup').addEvent('keyup', function(){
				var index = this.get('_index');
				var title = this.get('value');
				var marker = points[index];
				marker.setTitle(title);
				$('xtext_gmap_addr_points')
				.getFirst('option[value='+index+']')
				.set('text', title);
			});
		});
		if($chk(pop_iw) && pop_iw){
			google.maps.event.trigger(marker, 'click');
		}
	}
	
	$('xtext_gmap_add').removeEvents('click').addEvent('click',function(){
		var s_index = $('xtext_gmap_addr_select').get('value');
		if(!$chk(search_markers[s_index])) return;
		var s_marker = search_markers[s_index];
		s_marker.setVisible(false);
		add_marker(map, s_marker.getPosition(), s_marker.getTitle(), true);
	});
	$('xtext_gmap_add_by_cursor').removeEvents('click').addEvent('click',function(){
		this.set('disabled', true);
		var oldopt = {draggableCursor: map.get('draggableCursor')};
		var newopt = {draggableCursor: 'crosshair'};
		map.setOptions(newopt);
		var add_by_click = google.maps.event.addListener(map, 'click', function(e) {
			add_marker(map, e.latLng, null, true);
			$('xtext_gmap_add_by_cursor').set('disabled', false);
			map.setOptions(oldopt);
			google.maps.event.removeListener(add_by_click);
		});
	});
	$('xtext_gmap_del').removeEvents('click').addEvent('click',function(){
		var index = $('xtext_gmap_addr_points').get('value');
		if(!$chk(points[index])) return;
		$('xtext_gmap_addr_points').getFirst('option[value='+index+']').destroy();
		points[index].setMap(null);
	});
	var points = [];
	xtext_gmap_points = points;
	$('xtext_gmap_addr_points').set('html', '')
	.removeEvents('change').removeEvents('click')
	.addEvent('click',function(){this.fireEvent('change')})
	.addEvent('change', function(){
		var index = this.get('value');
		if(!$chk(points[index])) return;
		map.panTo(points[index].getPosition());
	});
	var geocoder = new google.maps.Geocoder();
	var search_markers = [];
	$('xtext_gmap_addr_select').set('html', '')
	.removeEvents('change').removeEvents('click')
	.addEvent('click',function(){this.fireEvent('change')})
	.addEvent('change', function(){
		if(!$chk(search_markers[this.get('value')])) return;
		var marker = search_markers[this.get('value')];
		search_markers.each(function(marker){
			marker.setVisible(false);
		});
		marker.setVisible(true);
		map.panTo(marker.getPosition());
	});
	$('xtext_gmap_addr_search').removeEvents('keypress').addEvent('keypress', function(e){
		var search_str = this.get('value');
		if(e.key != 'enter' || !search_str) return;
		e.preventDefault();
		//
		var search = {};
		if(search_str.match(/^[0-9\.]+(\s*[;,]\s*|\s+)[0-9\.]+$/)){
			var ll = search_str.split(/(\s*[;,]\s*|\s+)/, 2);
			search.location = new google.maps.LatLng(
				parseFloat(ll[0]),
				parseFloat(ll[1])
			);
		}else{
			search.address = search_str;
		}
		geocoder.geocode(search, function(results, status) {
			$('xtext_gmap_addr_select').set('html', '');
			search_markers.each(function(marker){ marker.setMap(null); });
			search_markers = [];
			if (status != google.maps.GeocoderStatus.OK){
				var errstr = xtext_lang_get('xtext_gmap_gcerr_unknown'); //'Неизвестная ошибка';
				switch(status){
				case google.maps.GeocoderStatus.ZERO_RESULTS:
					errstr = xtext_lang_get('xtext_gmap_gcerr_notfound'); //'Ничего не найдено';
					break;
				case google.maps.GeocoderStatus.REQUEST_DENIED:
					errstr = xtext_lang_get('xtext_gmap_gcerr_reqdeny'); //'Запрос отвергнут';
					break;
				case google.maps.GeocoderStatus.ERROR:
					errstr = xtext_lang_get('xtext_gmap_gcerr_transport'); //'Ошибка передачи запроса';
					break;
				case google.maps.GeocoderStatus.OVER_QUERY_LIMIT:
					errstr = xtext_lang_get('xtext_gmap_gcerr_limit'); //'Исчерпан лимит запросов';
					break;
				case google.maps.GeocoderStatus.INVALID_REQUEST:
					errstr = xtext_lang_get('xtext_gmap_gcerr_reqinvalid'); //'Неверный запрос';
					break;
				}
				(new Element('option', {value: '-', text: errstr}))
				.inject($('xtext_gmap_addr_select'));
				return;
			}
			results.each(function(result, index){
				var marker = new google.maps.Marker({
					map: map,
					position: result.geometry.location,
					title: result.formatted_address,
					zIndex: 0,
					visible: false,
					draggable: true
				});
				search_markers.push(marker);
				var option = new Element('option', {
					text: result.formatted_address,
					value: index
				}).inject($('xtext_gmap_addr_select'));
			});
		});
	});
}


var xtext_gmap_maps = [];
function xtext_gmap_process(parent){
	($type(parent) == 'element' || $type(parent) == 'document'
		? parent.getElements
		: $$
	)('.xtext-gmap').each(function(gmap){
		if(gmap.hasClass('xtext-gmap-ready')){
			return;
		}
		var map_cont = gmap.getFirst('.xtext-gmap-map');
		var opt = map_cont.get('_mapopt').parseQueryString();
		var mapopt = {};
		if($type(opt) == 'object'){
			mapopt.zoom = parseInt(opt.zoom);
			mapopt.mapTypeId = opt.type;
			var center = opt.center.split(/;/);
			mapopt.center = new google.maps.LatLng(
				parseFloat(center[0]),
				parseFloat(center[1])
			);
		}
		
		var map = new google.maps.Map(map_cont, mapopt);
		var points = [];
		
		var map_index = xtext_gmap_maps.length;
		map_cont.set('_map_index', map_index);
		
		var infowindow = new google.maps.InfoWindow({
	        content: '<div id="xtext_gmap_iw_'+map_index
	        	+'"><b class="xtext_gmap_point_title"></b>'
	        	+'<div class="xtext_gmap_point_info"></div></div>'
	    });
		
		gmap.getElements('.xtext-gmap-point').each(function(li){
			var marker = new google.maps.Marker({
				map: map,
				position: new google.maps.LatLng(
					parseFloat(li.get('_lat')),
					parseFloat(li.get('_lng'))
				),
				title: li.get('text')
			});
			
			google.maps.event.addListener(marker, 'click', function() {
				infowindow.open(map,marker);
				var iwcont = $('xtext_gmap_iw_'+map_index);
				iwcont.getFirst('.xtext_gmap_point_title').set(
					'text',
					marker.getTitle()
				);
				iwcont.getFirst('.xtext_gmap_point_info').set(
					'html',
					xtext_mathround(marker.getPosition().lat(),7)
					+' '+xtext_mathround(marker.getPosition().lng(),7)
				);
			});
			
			var index = points.length;
			points.push(marker);
			
			var lia = li.getFirst('a');
			lia.set('_map_index', map_index).set('_index', index)
			.addEvent('click', function(e){
				e.preventDefault();
				var context = xtext_gmap_maps[this.get('_map_index')];
				var marker = context.points[this.get('_index')];
				context.map.panTo(
						marker.getPosition()
				);
				google.maps.event.trigger(marker, 'click');
			});
			
			var sup_el = new Element('sup', {
				'class': 'xtext-gmap-kml'
			})
			.grab(new Element('a', {
				href: '#',
				text: '(kml)',
				events:{
					click: function(e){
						e.preventDefault();
						window.open(
							xtext_ajax_path('gmap', 'kmlsingle', {
								title: lia.get('text'),
								lat: marker.getPosition().lat(),
								lng: marker.getPosition().lng()
							}),
							'_blank'
						);
					}
				}
			}));
			
			sup_el.inject(lia, 'after');
			
		});
		
		xtext_gmap_maps.push({map: map, points: points});
		gmap.addClass('xtext-gmap-ready');
	});
}
