var isRunningIE7OrBelow = false;

//yandex api artur
var map = null;
var centerLatlng = null ;
var myOptions = null ;
var defaultSearchAction = '';
var inSearchResults=false;

var LocalMapConfig = {
	YMAPS_zoomToRadiusRatio: [
		[0,3335.0], 
		[1,3335.0], 
		[2,3335.0], 
		[3,1612.0], 
		[4,789.5], 
		[5,392.0], 
		[6,196.0], 
		[7,98.0], 
		[8,49.0], 
		[9,24.8], 
		[10,12.4], 
		[11,6.2], 
		[12,3.1], 
		[13,1.6], 
		[14,0.8], 
		[15,0.4],
		[16,0.2], 
		[17,0.1]
	],
    zoomToRadiusRatio: [
        [100, 1000000],
        [-9,1000000],
        [-8,60000],
        [-7,35000],
        [-6,16000],
        [-5,10000],
        [-4,4500],
        [-3,2500],
        [-2,1500],
        [-1,600],
        [0,350],
        [1,150]
    ],
    defaultLat: '55.750320',
    defaultLng: '37.646628',
    defaultRad: 50000,
    defaultZoomLvl: 8,
    defaultZoomRatio: 60000,
    zoomLvlMin: 0,
    zoomLvlMax: 14,
    zoomLvlMinNotRe: 3,
    zoomLvlMaxNotRe: 9,
    mapContainer: '#where_map_cnt'
};


var selectedwhere = null;
var selectedRadius = null;
var mapHasMoved;
var initMapHasMoved;
var initialMapStateForReset;
var selectedwherecookies = null;
var eventListeners=null;
var mapSubmitButtonController=null;
function initTheMap(){
	//eraseCrossDomainCookie('where_tooltip');
	//createCrossDomainCookie('where_tooltip','seen',30);
    
	//first of all try to get from here
    selectedwhere = getselectedwheredata();
    
	//get default or selected coords
	centerLatlng = new YMaps.GeoPoint(LocalMapConfig.defaultLng, LocalMapConfig.defaultLat);

	try{
		selectedwhere['initial_where'] = city_box.val();

		//no where filter, use last params from cookies
		if(selectedwhere.ignore_where==1){
			selectedwherecookies = getselectedwheredatacookie('user_geo');
			centerLatlng = new YMaps.GeoPoint(selectedwherecookies.lng, selectedwherecookies.lat);
			selectedRadius = selectedwherecookies.rad / 1000 ;
			city_box.val(selectedwherecookies.text);
			updateCitySelected(selectedwherecookies);
		    //if wheredata from cookies - update where info
		    /*if(selectedwherecookies!==null){
		    	gotoPopularWhereCity(selectedwherecookies.text,selectedwherecookies.lng,selectedwherecookies.lat,selectedwherecookies.rad);
		    }*/
		}
		else if( selectedwhere.lat>0 && selectedwhere.lng>0 && selectedwhere.rad>0 ){
			centerLatlng = new YMaps.GeoPoint(selectedwhere.lng, selectedwhere.lat);
			selectedRadius = selectedwhere.rad / 1000 ;
			//sync to cookies
			setselectedwheredatacookie('user_geo',selectedwhere['text'],selectedwhere);
		}
	}
	catch(e){
		/* if the wheredata inside the cookie, it has to be ALSO arrived from the server ,
		 * AT LEAST in that stage of proccess (when initTheMap called only once !!!) 
		 * if(selectedwhere = getselectedwheredatacookie()){
			centerLatlng = new YMaps.GeoPoint(selectedwhere.lng, selectedwhere.lat);
			selectedRadius = selectedwhere.rad / 1000 ;
		}*/
	}
	
	
	
	myOptions = {
      center: centerLatlng,
      zoom: LocalMapConfig.defaultZoomLvl
    };

	
    map = new YMaps.Map($(LocalMapConfig.mapContainer).get(0));
    map.setCenter(myOptions.center, myOptions.zoom);
    //map.addControl(new YMaps.TypeControl());
    //map.addControl(new YMaps.ToolBar());
    map.addControl(new YMaps.Zoom(), new YMaps.ControlPosition(YMaps.ControlPosition.TOP_LEFT, new YMaps.Point(5, 5)));
	//

	//
    //map.addControl(new YMaps.MiniMap());
    //map.addControl(new YMaps.ScaleLine());
    map.enableScrollZoom(true);
    //map.addControl(new YMaps.SearchControl());

    //add new map control element (html submit button)
    //map.addControl(new YMaps.ScaleLine());

    //add submit button controll
    mapSubmitButtonController = new MapSubmitButtonController(null);
    map.addControl(mapSubmitButtonController);
    
    if(getUrlInfo().section != 'realestate' ){
    	map.setMinZoom(LocalMapConfig.zoomLvlMinNotRe);
    	map.setMaxZoom(LocalMapConfig.zoomLvlMaxNotRe);
    }
    
    //save info for reset
    initialMapStateForReset = [myOptions.center,myOptions.zoom,selectedRadius,city_box.val()];

    defineOverlayStyles();
    drawLocationOverlay(selectedRadius);

    eventListeners = {} ;
    initMapHasMovedFlag();
    mapHasMoved=true;

    
    eventListeners.mapListenerBoundsChange = 
    	YMaps.Events.observe(map,map.Events.BoundsChange, function (map,mEvent) {
    		drawLocationOverlay(null);
    		mapHasMoved=true;
    		initMapHasMoved=true;
    		//console.debug('mapListenerBoundsChange triggered');
    	});
    
    eventListeners.mapListenerBeforeMouseDown = 
    	YMaps.Events.observe(map,map.Events.BeforeMouseDown, function (map,mEvent) {
    		city_box.blur();
    	});
    
}

function initMapHasMovedFlag(){
	initMapHasMoved = selectedwherecookies!==null || Boolean(selectedwhere.ignore_where);
}


//--==-- 
//ADD SUBMIT BUTTON ON THE MAP
//--==--
function MapSubmitButtonController(options) {

	this._createElements = function () {
		this.containerhtml = '<div></div>';
		
		this.buttonhtml = '<div class="map_button_bg"></div><div class="map_button_cnt"><button value="" type="submit" id="location_submit_where" class="yt-uix-submit-button">'
			+ '<span class="yt-uix-submit-button-content">ИСКАТЬ</span>'
			+ '</button></div>';
		
		this.container = YMaps.jQuery(this.containerhtml);
		this.container.html(this.buttonhtml);
		this.button = YMaps.jQuery(this.container.find('button').get(0));

	};

	
	this.onAddToMap = function (map, position) {

		this._createElements();

        this.map = map;
        this.position = new YMaps.ControlPosition(YMaps.ControlPosition.BOTTOM_RIGHT, new YMaps.Size(6, 6));

        // css for the div container
        this.container.css({
            position: "absolute",
            zIndex: YMaps.ZIndex.CONTROL +1 ,
            background: 'transparent',
            listStyle: 'none',
            padding: '0',
            margin: 0
        });
        
        // apply element position on the map
        this.position.apply(this.container);
        
        // add to map
        this.container.appendTo(this.map.getContainer());
        
		this.button.bind('click',onMapSubmitButtonTrigger);
    };


    this.onRemoveFromMap = function () {
        this.container.remove();
        this.container = this.map = null;
    };
    

    //return dom element of the submit button (jquey)
    this.getButton = function () {
    	return this.button;
    };
}


//--==-- 
//DEFINE STYLES AND OPTIONS
//--==--
var locationOverlayStyle = null ;
var innerCircleStyle = null;
var locationOverlayOptions = null;
function defineOverlayStyles(){

	locationOverlayStyle = new YMaps.PolygonStyle();
	locationOverlayStyle.fill = 1;
	locationOverlayStyle.outline = 0;
	//locationOverlayStyle.strokeWidth = 0;
	//locationOverlayStyle.strokeColor = "ffff0088";
	locationOverlayStyle.fillColor = "00FFFF33";
	

	innerCircleStyle = new YMaps.PolygonStyle();
	innerCircleStyle.fill = 0;
	innerCircleStyle.outline = 1;
	innerCircleStyle.strokeWidth = 5;
	innerCircleStyle.strokeColor = "DF6929FF";
	//innerCircleStyle.fillColor = "00FFFF80";

	locationOverlayOptions = {
			hasBalloon: false,
			hasHint: false,
			interactive: YMaps.Interactivity.NONE,
			style: {"polygonStyle":locationOverlayStyle}
	};

	innerCircleOptions = {
			hasBalloon: false,
			hasHint: false,
			interactive: YMaps.Interactivity.NONE,
			style: {"polygonStyle":innerCircleStyle}
	};
}
/*
//innerCircleStyle.fill = 0; //innerCircleOptions.interactive = YMaps.Interactivity.INTERACTIVE; //innPol.setOptions(innerCircleOptions ); 
//--==--: DEBUG STYLES in browser console:
locationOverlayStyle.fill = 1;
locationOverlayStyle.outline = 0;
locationOverlayStyle.fillColor = "00FFFF33";
innerCircleStyle.fill = 0;
innerCircleStyle.outline = 1;
innerCircleStyle.strokeWidth = 10;
innerCircleStyle.strokeColor = "ffAA0055";
outPol.setOptions({"style": locationOverlayOptions.style } );
innPol.setOptions({"style": innerCircleOptions.style } );
*/

/* how much space in percents dedicated for PADDING the radius on BOTH sides*/
var radiusPadding = 0.1 ;
function getBoundsFromRadius(center, radiusKm){
	var radiusInLatDeg = latKmToDeg(radiusKm, center.getLat()) * 2 * (1+radiusPadding);
	return YMaps.GeoBounds.fromCenterAndSpan( center, new YMaps.Size(0,radiusInLatDeg));
}
function getRadiusFromBounds( center, bounds){

	var radiusInPercents = (1 - radiusPadding) / 2 ;
	var radiusLatDistance = bounds.getSpan().y * radiusInPercents ;
	//var radiusNorthPoint = bounds.getCenter().copy().moveByY(radiusLatDistance);
	
	return latDegToKm(radiusLatDistance, center.getLat());
}


var outPol = null, outPoints=null, scaledBounds=null;
var innPol = null, innPoints=null;
var scaleFactor = 3;
var lastMapCoords={};
function drawLocationOverlay(radiusKm){
	var center = map.getCenter();
	/* --==-- FIND AND SET BOUNDS FOR THE RADIUS --==-- */
	if(radiusKm && radiusKm>0.050){
		var radBounds = getBoundsFromRadius(center, radiusKm);
		map.setBounds(radBounds);
		//console.debug("GET BOUNDS FROM RADIUS(1):"+radiusKm);
		//console.debug("GET BOUNDS FROM RADIUS(2):"+getRadiusFromBounds(center, radBounds));
		lastMapCoords.desiredRadiusKm = radiusKm ;
	}

	/* --==-- GET RADIUS FROM BOUNDS (zoom to radius ratio is the final size) --==-- */
	radiusKm = getRadiusFromBounds(center, map.getBounds());
	//console.debug("GET RADIUS FROM BOUNDS(2):"+radiusKm);

	lastMapCoords.center = center;
	lastMapCoords.radiusKm = radiusKm ;
	
	
	/* --==-- DRAW OUTER POLYGON --==-- */
	//outPol = new YMaps.Polygon([],{"style":{"polygonStyle":locationOverlayStyle}});
	outPol = new YMaps.Polygon([],locationOverlayOptions);
	outPoints = drawCirclePol(center,radiusKm);

	//in order to avoid expensive Math operations again, save inner circle path 
	innPoints = outPoints.slice(0);//drawCirclePol(center,radiusKm);

	scaledBounds = YMaps.GeoBounds.fromCenterAndSpan(
			center, map.getBounds().getSpan().scale(scaleFactor) );
	
	//points.push(new YMaps.GeoPoint( scaledBounds.getRight(),center.getLat() ));
	outPoints.push(scaledBounds.getRightTop());
	outPoints.push(scaledBounds.getLeftTop());
	outPoints.push(scaledBounds.getLeftBottom());
	outPoints.push(scaledBounds.getRightBottom());
	outPoints.push(scaledBounds.getRightTop());
	outPol.setPoints(outPoints);


	/* --==-- DRAW INNER POLYGON --==-- */
	innPol = new YMaps.Polygon([],{"style":{"polygonStyle":innerCircleStyle}});
	/*improved performance innPoints = drawCirclePol(center,radiusKm);*/
	innPol.setPoints(innPoints);
	
	map.removeAllOverlays();
	map.addOverlay(outPol);
	map.addOverlay(innPol);
	//alert ("DONE 111") ;
}

//Each degree of latitude is approximately 69 miles (111 kilometers) , yandex use this constant
//according to its examples
var dKMsInLat = 112.2 ;
function getDistanceOnLatScale(lat1,lat2,relLat){
	if(!relLat) relLat =0; 
	//return map.coordSystem.distance(new YMaps.GeoPoint(map.getCenter().getLng(),lat1), new YMaps.GeoPoint(map.getCenter().getLng(),lat2));
	return (new YMaps.GeoPoint(0,relLat+lat1)).distance(new YMaps.GeoPoint(0,relLat+lat2)) / 1000;
		
}
function latDegToKm(deg,relLat){
	return getDistanceOnLatScale(0,deg,relLat);
}
function latKmToDeg(km,relLat){
	return km/latDegToKm(1,relLat);
}
/**
 * Draw circle polygon and return it's GEO POINTS,
 * from http://api.yandex.ru/maps/jsapi/examples/circle.html
 *  
 * to improve performace need to use bresenharm algorythm and mirror reflections
 * (to do only 1/n part of the circle sin/cos operations..) 
 * --Artur
 * 
 * @param map
 * @param radius
 * @return
 */
function drawCirclePol(center, radius) {
	
	var accuracy=60,
	
	// Откладываем геоточку от центра к северу на заданном расстоянии
	northPoint = new YMaps.GeoPoint(center.getLng(), center.getLat() + latKmToDeg(radius, center.getLat())/*radius / dKMsInLat */),
	
	// Пиксельные координаты на последнем масштабе
	pixCenter = map.coordSystem.fromCoordPoint(center),
	
	// Радиус круга в пикселях
	pixRadius = pixCenter.getY() - map.coordSystem.fromCoordPoint(northPoint).getY(),
	
	// Вершины многоугол
	points = [],
	
	// Вспомогательные переменные
	twoPI = 2 * Math.PI,
	delta = twoPI / accuracy;
	
	for (var alpha = 0; alpha < twoPI; alpha += delta) {
		points.push(
			map.coordSystem.toCoordPoint(
				new YMaps.Point(
						Math.cos(alpha) * pixRadius + pixCenter.getX(),
						Math.sin(alpha) * pixRadius + pixCenter.getY()
				)
			)
		);
	}
	//alert ("DONE 222") ;
	return points;
}
















/*
 * 		GLOBAL AUTOCOMPLETE FOR WHERE 
 */

var city_selected = [];
var city_box=null;
var lastPanToBounds = {'lat':null,'lng':null};

function updateMapFromAc(item){
	
	if(!item.lat || !item.lng){
		return false;
	}
	if(lastPanToBounds.lat==item.lat && lastPanToBounds.lng==item.lng){
		city_box.autocomplete('close');
		//$("#location_submit_where").focus();
		mapSubmitButtonController.getButton().focus();
		return 1;
	}

	var map_cr_state = [map.getCenter(),map.getZoom()] ;
	var defZoom =8 ;// because defRadius = 50 km

	map.panTo( new YMaps.GeoPoint(item.lng,item.lat), {
		flying:true,
		callback:function(s){
			//console.debug(s);
			if(s===YMaps.State.FAILURE){
				map.setCenter(map_cr_state[0],map_cr_state[1]);
			}
			else if(s===YMaps.State.SUCCESS){
				lastPanToBounds = {lat:item.lat,lng:item.lng};
				if(item.bounds){
					map.setBounds(item.bounds);
					//console.debug('case 1');
				}
				else if (item.radius>0.050){
					//console.debug('case 2');
					map.setBounds(getBoundsFromRadius(map.getCenter(),item.radius));
				}
				else{
					//console.debug('case 3');
					map.setZoom(defZoom);
				}
				mapHasMoved = false;

				
				// if to submit the new WHERE after pan finished
				// eg. when called from gotoPopularWhereCity
				try{ 
					if(item.submit_after_pan===true){
						//close the where window and submit
						//mapSubmitButtonController.getButton().click();
						setTimeout('uniquenamesubmitclickcallback()', 1000);
						//onMapSubmitButtonTrigger(null,null,null);
						//setTimeout('eval($("#rfclkWhere_close").click())', 2000);
					} 
				} 
				catch(e) {
					//;
				} 
				
			}
			city_box.focus();
			city_box.autocomplete('close');
		}//end callback
	});//end panTo
	
	return true;
}
function uniquenamesubmitclickcallback(){
	onMapSubmitButtonTrigger(null,null,null);
	setTimeout('eval($("#rfclkWhere_close").click())', 1500);
}

/**
 * Where autocomplete
 */
function autocomplete_where(){

	city_box.autocomplete({
		minLength: 1,
		delay: 200,
		selectFirst: true,
		source: ac_where_clbk,
		
		select: function(event, ui) {
			//console.debug("WHERE AC EVENT:  'SELECT'");
			city_box.blur();//bind the focus out of this input
			city_selected = ui.item;
			updateMapFromAc(city_selected);
		},
		
		focus: function(event, ui) {
			//console.debug("WHERE AC EVENT:  'FOCUS'");
		},
		
		close: function(event, ui) {
			//console.debug("WHERE AC EVENT:  'CLOSE'");
		},

		change: function(event, ui) {
			//console.debug("WHERE AC EVENT:  'CHANGE 111'");
		},
		open: function(event, ui) {
			//console.debug("WHERE AC EVENT:  'OPEN'");
		},
		search: function(event, ui) {
			//console.debug("WHERE AC EVENT:  'SEARCH'");
		},
		create: function(event, ui) {
			//console.debug("WHERE AC EVENT:  'CREATE'");
		}
	});
	
}
	




/*
 * CACHE ALGORYTHM
 */
var globalCache = null;
var apiCache = null;

function CacheManipulator(name){
	
	this.name=name;
	this.cache = {} ;
	this.hashMap = [null] ;
}
CacheManipulator.prototype.reset=function(){
	this.cache = {} ;
	this.hashMap = [null] ;
};
CacheManipulator.prototype.addKey=function(name){
	return this.hashMap.push(name) - 1;
};
CacheManipulator.prototype.getKey=function(name){
	return this.hashMap.indexOf(name);
};
CacheManipulator.prototype.addElement=function(name,element){
	var key = -1 ;
	if((key=this.getKey(name))===-1){
		key = this.addKey(name);
	}
	return this.cache[key] = element;
};
CacheManipulator.prototype.getElement=function(name){
	var i = this.getKey(name);
	if(i !== -1 && this.cache[i]!==null){
		return this.cache[i];
	}
	return false;
};
CacheManipulator.prototype.getElementByKey=function(key){
	return this.cache[key];
};


function ac_fix_str(str){
	return (new String(str)).trim().replace(/[\s]+/g,' ').toLowerCase();
}



function ac_where_clbk(theobj,resp){
		/*
	var global_resp=null;
	var global_resp_flag = true;
	if(global_resp_flag){
		//console.debug("response initialization");
		global_resp = resp;
		global_resp_flag=false;
	}*/
		
	var name = ac_fix_str(theobj.term);
	
	//check if exists in cache and responde
	var e = globalCache.getElement(name);
	if(e){
		resp(e);
		//console.debug("From cache, [name:"+name+',key:'+globalCache.getKey(name)+']');
		return ;
	}
	
	//else two options
	// 1. ajax autocomplete
	ac_where_ajax(name,resp);
	return;
	
	// 2. api geocode request - this is different trigger(on submit button)
}


var ac_where_ajax_flag = true;
var ac_where_ajax_ts = null;
/**
 * autocomplete with ajax
 */
function ac_where_ajax(str,resp){
	
	if(!ac_where_ajax_flag && (new Date()).getTime()-ac_where_ajax_ts<10000){
		//console.debug('ajax busy');
		return;
	}
	ac_where_ajax_flag = false ;
	ac_where_ajax_ts = (new Date()).getTime();
	
	str = ac_fix_str(str);
	
	$.ajax({
		url: "/ajax/autocompletewhere",
		dataType: 'json',
		data: {'q':str},
		type: 'POST',
		error: function(a,b,c){
			ac_where_ajax_flag = true ;
			return false;
		},
		resp_clbk: resp, 
		success: function(json){ 
			var list = [];
			if(json.length > 0){
				$(json).each(function(id,item){
					list.push({
						'text':item.l_geo_city,
						'label':item.l_geo_city,
						'value':item.l_geo_city,
						'both':item.l_geo_city,
						'lat':item.l_latitude,
						'lng':item.l_longitude,
						'bounds':null,
						'radius':null,
						'fromapi':false
						
					});
				});
			}

			globalCache.addElement(str, list);
			this.resp_clbk(list);//even with zero results! (to kill prev request results)
			
			if(list.length){
				//
			}
			//console.debug("From ajax, [name:"+str+',key:'+globalCache.getKey(str)+']');
			//console.debug(list);
			ac_where_ajax_flag = true ;
			return;
		} /* on success callback */
	}); /* getjson */
}


/**
 * change location from popular where cities 
 */
var _active_button_where;
function gotoPopularWhereCity(text,lng,lat,radius, button){
	if(!CheckSubmit()){
		return;
	}
	var ui = {item: 
		{
			'text':text,'label':text,'value':text,'both':text,
			'lng':lng, 'lat':lat, 'radius':radius,
			'bounds':null,
			'fromapi':false,
			'submit_after_pan':true
		}
	};
	//console.debug(ui);
	city_box.autocomplete('option','select').call(null,null,ui);
	city_box.val(text);
	$(button).addClass('active');
	if(_active_button_where && _active_button_where!==button )$(_active_button_where).removeClass('active');
	_active_button_where = button;
}

function updateCitySelected(source){
	if(!source){
		city_selected=[];
	}
	else{
		city_selected = {
			'text':source.text,'label':source.text,'value':source.text,'both':source.text,
			'lat':source.lat,'lng':source.lng,
			'radius':source.rad,
			'bounds':null,'fromapi':false};
	}
}





var geocoder=null;
/**
 * @returns Array
 * 		(text,label,value,both,lat,lng,bounds,radius)
 * 
 */
function ac_where_api(where,howmuch){

	howmuch=5;
	var geoCodeOptions = {
			results: howmuch, 
			boundedBy: map.getBounds(),
			//strictBounds: false,
			//kind:'locality',
			prefLang:'ru'
	};
	
	where = ac_fix_str(where);
	
	var apicache=-1;
	if((apicache=apiCache.getElement(where))){
		switch(apicache[0]){
			case 'found':
				//console.debug("API FOUND PREVIOUSLY");
				city_box.autocomplete('search');
				break;
			case 'alias':
				//console.debug("API FOUND PREVIOUSLY, ALIAS OF "+apicache[1]);
				city_box.autocomplete('search');
				break;
			case 'empty':
				//console.debug("API FOUND PREVIOUSLY, EMPTY");
				break;
		}
		return false;
	}
	
	geocoder = new YMaps.Geocoder(where, geoCodeOptions);

    YMaps.Events.observe(geocoder, geocoder.Events.Load, function (p) {
    	//console.debug('GEOCODE LOAD');
    	geocoder=p;
    	var list = [];
    	
        if (p.length()) {//found
        	p.forEach(function(result,index,group){
        	    //console.debug(result);
        	    //console.debug(result.kind+'  |  '+result.text.replace(/^\s*Россия[\s+\,]+/,''));
        	    //var name = parseGeoResName(result);
        	    var name = result.text.replace(/^\s*Россия[\s+\,]+/,'');
        	    //if(!name)return false;

        	    list.push({
					'text':name,
					'label':name,
					'value':name,
					'both':name,
					'lat':result.getGeoPoint().getLat(),
					'lng':result.getGeoPoint().getLng(),
					'bounds':result.getBounds().copy(),
					'radius':null,
					'fromapi':true
				});
        	});
        	
        	//add to cache and trigger autocomplete
        	globalCache.addElement(this.where, list);
        	apiCache.addElement(this.where, ['found']);
        	if(list.length 
        			&& ac_fix_str(list[0].text)!==this.where){
        		globalCache.addElement(ac_fix_str(list[0].text), list);
        		//console.debug("inserted suggested name to cache");
        		//console.debug(ac_fix_str(list[0].text));
        		apiCache.addElement(ac_fix_str(list[0].text), ['alias',this.where]);
        	}
        		
        	//console.debug(this.where+'2');
        	//console.debug(list);

        	//- bind all results to autocomplete and trigger search
        	city_box.autocomplete('search');
        	
        }else {
            //console.debug("Ничего не найдено");
            apiCache.addElement(this.where, ['empty']);
        }
        city_box.focus();
        return;
    },{'where':where});
    
    YMaps.Events.observe(geocoder, geocoder.Events.Fault, function (p,error) {
    	//console.debug('GEOCODE FAULT'+error);
    	city_box.focus();
    	return;
    	//return -1 or throw ErrorType
    });
 
    return true;
}


var revgeocoder = null;
function where_rgeocode(geoPoint,l_goto_args){
	//console.debug('REV GEOCODE CALL: '+l_goto_args[2]);
	
	var r_geoCodeOptions = {
			results: 1, 
			//boundedBy: map.getBounds(),
			//strictBounds: false,
			kind:'locality',
			prefLang:'ru'
	};
	
	if(geoPoint===void 0 || l_goto_args === void 0 || l_goto_args.length!==4){
		return false;
	}
	revgeocoder = new YMaps.Geocoder(geoPoint, r_geoCodeOptions);


	YMaps.Events.observe(revgeocoder, revgeocoder.Events.Load, function (p) {
		//console.debug('REV GEOCODE EVENT LOAD FOR: '+this.l_goto_args[2]);
		revgeocoder=p;

		if (p.length()) {//found
			var result = p.get(0);
			//console.debug(result);
			//console.debug(result.kind+'  |  '+result.text.replace(/^\s*Россия[\s+\,]+/,''));

			this.l_goto_args[2] = result.text.replace(/^\s*Россия[\s+\,]+/,'');
			
		}else {
			//console.debug("Ничего не найдено");
		}
		$("#lockRf .val").text(this.l_goto_args[2]);
		try{location_goto(this.l_goto_args);}catch(e){UnlockSubmit();}
		return;
		}, {'l_goto_args':l_goto_args}
	);
	
	/* if no where from rgeocode put RUSSIA */
	YMaps.Events.observe(revgeocoder, revgeocoder.Events.Fault, function (p,error) {
		//console.debug(error);
		$("#lockRf .val").text(this.l_goto_args[2]);
		try{location_goto(this.l_goto_args);}catch(e){UnlockSubmit();}
		return;
		},{'l_goto_args':l_goto_args}
	);


	return true;
}




function parseGeoResName(result){
	var tempStr='', name='', tempObj=null;
	try{
		if((tempObj=result.AddressDetails.Country)!=void 0){
			/*IF IN RUSSIA ?
			 * if(CountryNameCode!='RU'){
	
		 	}*/
			
			if((tempObj=tempObj.Locality)!=void 0){
	
				name = '';
	
				//city name, usually
				if((tempStr=tempObj.LocalityName).length>0){
					name += tempStr;
	
					//street name, usually
					if((tempObj=tempObj.Thoroughfare)!=void 0){
						if((tempStr=tempObj.ThoroughfareName).length>0){
							name += ', '+tempStr;
							//number
							if ((tempObj.Premise)!=void 0 && (tempStr=tempObj.Premise.PremiseNumber).length>0){
								name += ', '+tempStr;
							}
						}
					}
				}
			}
		}
		else if(result.text.length>1){
			name = result.text;
		}

	}
	catch(e){
		//
	}
	return name.replace(/^\s*Россия[\s+\,]+/,'');
}












/**
 * 	Goto new url location specified by function arguments .
 * @param urlinfo - args propertry of this object should hold the controller name in args[0] 
 * @param what - what string
 * @param where - where string
 * @param get - get params
 * @param ignore_where - bool indicator
 */
function location_goto(urlinfo,what,where,get/*,ignore_where*/){
    
	//console.debug('locaion goto trigger 1');
	if(arguments.length===1 && arguments[0].length!==void 0 && arguments[0].length===4){
		//console.debug('location goto trigger 3');
		what=arguments[0][1];
		where=arguments[0][2];
		get=arguments[0][3];
		urlinfo = arguments[0][0];
	}
	
	var ignore_where=false;
	if(arguments.length===5){
		ignore_where=arguments[4];
	}
	//console.debug(ignore_where);
    
	var query_str=[];
	
	var ignoregetkeys = ['page','shared'];
	if(ignore_where){ ignoregetkeys.push('lat','lng','rad'); }
	for(var i=0; i<ignoregetkeys.length; i++){
		if(ignoregetkeys[i] in get){
			delete get[ ignoregetkeys[i] ];
		}
	}
	
	for(var key in get){
		query_str.push(key+'='+get[key]);
	};
	query_str=query_str.join('&');

	if(what===void 0) what='';


	if(!ignore_where){
		setselectedwheredatacookie('user_geo',where,get);
		$("input[name='ignore_where']").val(Number(ignore_where));
	}
	else{
		$("input[name='ignore_where']").val(Number(ignore_where));
	}
	
	if(inSearchResults){
	    // do post immediately
	    window.location.href = '/'+urlinfo.args[0]+'/'+what+'/'+where+"?"+query_str;
	    LockSubmit();

	    return;
    }
    else{
    	updatewheretitle(where,get.rad);
        $('#search_form').attr('action', defaultSearchAction+'/'+where+'/'+query_str);
        $("input[name='wheretext']").val(where);
        $("input[name='lat']").val(get.lat);
        $("input[name='lng']").val(get.lng);
        $("input[name='rad']").val(get.rad);
        //jsddm_close();
        $("#rfclkWhere_close").click();

    	return false;
    }
}



/*
 * LOCK STATUSes: FALSE - BUSSY , TRUE - FREE
 */
var SubmitStatus= [true,null,5000];
function LockSubmit(){
	SubmitStatus[0]=false;
	SubmitStatus[1]=(new Date()).getTime();
}
function UnlockSubmit(){
	SubmitStatus[0]=true;
	SubmitStatus[1]=null;
}
function CheckSubmit(){
	if((new Date()).getTime()-SubmitStatus[1]>SubmitStatus[2]){
		 UnlockSubmit();
	}
	return SubmitStatus[0];
}


//checks in search results page
function is_in_sr_page(action,section){
	var validActions = ['search','category','rent','sale'];
	var validSections= ['vehicles','realestate','jobs'];
	if(validActions.indexOf(action)==-1 || validSections.indexOf(section)==-1){
		return false;
	}
	//exceptions:
	if(section=='realestate' && action=='search'){
		return false;
	}
	return true;
}


/*
* DOCUMENT READY
*/
$(document).ready(function(){
	defaultSearchAction = $('#search_form').attr('action');

	// determine if we are on a home page or a search result
	var urlinfo = getUrlInfo();
	if(is_in_sr_page( (urlinfo.args[0] || ''), urlinfo.section)){
        inSearchResults = true;
    }
	else{
		//put trigger on search button
		
	}

    //before www integration:
    city_box = $('#location_item_form input#location_item');
	autocomplete_where(); 
	
    globalCache = new CacheManipulator('global');
	apiCache = new CacheManipulator('api');
	
	$("#location_findonmap_submit").click(function(e,v){
	
		e.preventDefault();
		
		/*
			is what inside the input was choosed by user ? 
		 */
		if(city_selected.value 
				&& ac_fix_str(city_selected.value)===ac_fix_str(city_box.val()) 
				&& !mapHasMoved){
			//console.debug('u selected on submit indication test whatever...');
			city_box.autocomplete('close');
			//$("#location_submit_where").focus();
			mapSubmitButtonController.getButton().focus();
			return;
		}
		
		//parseGeoResults('Москва, проспект мира')
		var where = city_box.val();
		city_box.blur();
		if(!ac_where_api(where)){
			city_box.focus();
		}

		//move map to the first result 
		//bind results to input tag ??? (like autocomplete) 
		//means trigger ac search method
		
	});
	
	$("#location_item_form").submit(function(e,v){
		e.preventDefault();
		//console.debug('location_item_form click');
		$("#location_findonmap_submit").click();
	});
	
	
	$("#location_reset_map").click(function(e,v){
	    map.setCenter(initialMapStateForReset[0],initialMapStateForReset[1]);
	    drawLocationOverlay(initialMapStateForReset[2]);
	    updateCitySelected(selectedwherecookies);
	    city_box.val(selectedwhere['initial_where']);
	    if(!inSearchResults)updatewheretitle(initialMapStateForReset[3],initialMapStateForReset[2]*1000);
	    initMapHasMovedFlag();
	});
	
	$("#where_ignore").click(function(e,v){
		var urlinfo=getUrlInfo();
		location_goto(urlinfo, urlinfo.args[1], "ВСЯ Россия", urlinfo.get, true);
		$("#rfclkWhere_close").click();
		//jsddm_close(); // in location_goto also
	});
	
	/* if the page loaded with opened map container, init the map imidiatly, otherwice wait untill user clicks on the slider*/
	var _slide_container = '#where_slide_container';
	if($(_slide_container).hasClass('where_is_opened')){
		try{ initTheMap(); window.initTheMapOnce=true;} catch(e){/*failed to init map*/;}
	}
	
	/* if there are metros or neighs available - open the map container once and put cookie */
	var _where_tab_neighs = '#where_tab_neighs';
	var _where_tab_metros = '#where_tab_metros';
	if(!inSearchResults || urlinfo.section!='realestate' || readCookie('openWhereTabOnceI')){
		/* this check also applied in the views so ... not mandatory || urlinfo.section!='realestate'*/
		return;
	}
	else{
		
		if( $(_where_tab_neighs+','+_where_tab_metros).parent().hasClass('active') ){
			item_closeHint(hintItemGlobalAccesble);
			slide_where();
			createCrossDomainCookie('openWhereTabOnceI','true',180);
		}
	}
	
});


//$("#location_submit_where").click(function(e,v){
function onMapSubmitButtonTrigger(e,v,c){

	if(e){
		e.preventDefault();
	}

	if(!CheckSubmit()){
		return;
	}else{
		LockSubmit();
	}
	
	//check if changes were made
	var urlinfo = getUrlInfo();

	var wherestring='';
	if(initMapHasMoved===false){
		//no changes were applied
		$("#rfclkWhere_close").click();
		//jsddm_close();
		return;
	}

	var notfound=true;
	if (lastMapCoords && lastMapCoords.center){

		urlinfo.get['lng'] = lastMapCoords.center.toString().split(',')[0];
		urlinfo.get['lat'] = lastMapCoords.center.toString().split(',')[1];
		urlinfo.get['rad'] = parseInt(lastMapCoords.radiusKm * 1000);
		//if selected area inside selected where area from autocompletion
		// TODO: I think depricated ... This code never runs but check with artur
		if(city_selected.text !== void 0 ){
			if(!mapHasMoved || 
					city_selected.fromapi && city_selected.bounds.contains(lastMapCoords.center)){
				wherestring = city_selected.text;
				//console.debug('option 1');
				notfound=false;
			}
			else if(city_selected.radius!==null 
				&& (new YMaps.GeoPoint(city_selected.lng,city_selected.lat)).distance(map.getCenter())<city_selected.radius*1000){
				wherestring = city_selected.text;
				//console.debug('option 2');
				notfound=false;
			}
		}
		//else use reverse geocoding for WHERE string
		if( notfound && where_rgeocode( lastMapCoords.center, [
					  urlinfo, urlinfo.args[1], lastMapCoords.center.toString(), urlinfo.get ] 
					  ) !== false
				  ){
				//console.debug('option 3');
			return ;
		}
	}
	else if(selectedwhere){
		//will be continue
		//if selected area inside INITIAL selected where area (within radius distance)
		if((new YMaps.GeoPoint(selectedwhere.lng,selectedwhere.lat)).distance(map.getCenter())<selectedwhere.rad){
			wherestring = selectedwhere['initial_where'];
		}
		return false;
	}
	//console.debug('hhhhere');
	//console.debug(wherestring);
	location_goto(urlinfo,urlinfo.args[1],wherestring,urlinfo.get);
	return ;
};
//});


function getselectedwheredatacookie(cname){
	var userGeoSetting = decodeURIComponent(readCookie(cname)).replace('+',' ');;
	
//console.debug(userGeoSetting);
	
	userGeoSetting = userGeoSetting.split('&');

	var selectedwhere={"lat":0,"lng":0,"rad":0,"text":''};
	
    for (var i=0; i<userGeoSetting.length; i++) {
        var tmp = userGeoSetting[i].split('=');
        if(!(tmp[0] in selectedwhere)){
        	return null;
        }
        selectedwhere[ tmp[0] ] = tmp[1];
    }

    return selectedwhere;
}


function setselectedwheredatacookie(cname,where,geovals){
	var geo_str=[];

	var keys = ["lng","lat","rad"];
	//validate all values exists
    for(var i=0; i<keys.length; i++){
    	var k = keys[i];
		if(!(k in geovals)){return false;}
		geo_str.push(String(k+'='+geovals[k]));
	}

    if(where===void 0){	where='';}
    geo_str.push('text='+(where!==void 0?where:''));

    geo_str = encodeURIComponent(geo_str.join('&'));

	// set a cookie with the new geo data
	eraseCrossDomainCookie(cname);
	createCrossDomainCookie(cname,geo_str,30);

	return true;
}

function updatewheretitle(text,radius){
	var formattedRadius = String(radius>=50?radius/1000:'').replace(/^([\d]+(\.\d{1,2})?).*$/,'$1').replace('.00','');
	// set form action parameters
    $("#geoinfo_id").html(text+(formattedRadius>0?' <small>+ '+formattedRadius+' км</small>':''));
}

