var Ambush = new Object; 



/////////////////////////////////////////////////////////////////////////////////
// file: ./ambush/Util.js
/////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////
// Различные утилиты для работы с засадой.
// (C) moback.ru

//	Ambush.Util = new Object;
Ambush.Util = {
	version: '1.1.7',
	rootUrl: '/js/',
	context: this,
	versioninig: false
}
/**
* Возвращает кук по его имени.
*/
Ambush.Util.getCookie = function(name){
	var cookie = " " + document.cookie;
	var search = " " + name + "=";
	var setStr = null;
	var offset = 0;
	var end = 0;
	if (cookie.length > 0) {
		offset = cookie.indexOf(search);
		if (offset != -1) {
			offset += search.length;
			end = cookie.indexOf(";", offset)
			if (end == -1) {
				end = cookie.length;
			}
			setStr = unescape(cookie.substring(offset, end));
		}
	}
	return(setStr);
}

/**
* Устанавливает кук.
*/
Ambush.Util.setCookie = function(name, value, days, path, domain, secure){
	var expires;
	if (days) {		
		var date = new Date();
		date.setTime(date.getTime()+(days*24*60*60*1000));
		expires = "; expires="+date.toGMTString();
	}

	var cookies = name + "=" + escape(value) +
        ((expires) ? expires : "") +
        ((path) ? "; path=" + path : "; path=/") +
        ((domain) ? "; domain=" + domain : "") +
        ((secure) ? "; secure" : "");

	document.cookie = cookies + ";";
}

Ambush.Util.includeToHead = function(js)
{
	var script; 
	script = document.createElement("script");
	script.src = js;
	script.type = "text/javascript";
	script.charset = "utf-8";
	document.getElementsByTagName("head")[0].appendChild(script);
}

/**
 * @author Vladimir Kolesnikov <voloko@gmail.com>
 * @copyright (c) Vladimir Kolesnikov <voloko@gmail.com>
 */
/**
 * @param {Object} object
 * @param {String} name
 * @param {Object?} value
 * @param {bool?} forceSet
 */
Ambush.Util.evalProperty = function(object, name, value, forceSet) {
	if(object) {
		if(!object[name] || forceSet) object[name] = value || true;
		return object[name];
	}
	return null;
}
/**
 * @param {String} path
 * @param {Object?} context
 * @param {Object?} value
 * @param {bool?} forceSet
 */
Ambush.Util.evalPath = function(path, context, value, forceSet) {
	context = context || Ambush.Util.context;
	var pos = path.indexOf('.');
	if(pos == -1) {
		return Ambush.Util.evalProperty(context, path, value, forceSet);
	} else {
		var name = path.substring(0, pos);
		var path = path.substring(pos + 1);
		var obj = Ambush.Util.evalProperty(context, name, value);
		return Ambush.Util.evalPath(path, obj, value, forceSet);
	}
}

/**
 * @param {String} path
 * @param {float} version
 * @return {String}
 */
Ambush.Util.pathToUrl = function(path, version) {
	return Ambush.Util.rootUrl + path.replace(/\./g, '/') + 
		(Ambush.Util.versioninig ? '.v' + version : '') + '.js';	
}
/**
 * @type {Array}
 */
Ambush.Util.loadedModules = {};

/**
 * @param {String} path
 * @param {float} version
 */
Ambush.Util.module = function(path, version) {
	version = version || 1.0;
	Ambush.Util.loadedModules[path] = Ambush.Util.loadedModules[path] ? Math.max(Ambush.Util.loadedModules[path], version) : version;
	return Ambush.Util.evalPath(path, null, {});
}

/**
 * @param {String} path
 * @param {float} version
 */
Ambush.Util.include = function(path, version) {
	version = version || 1.0;
	if(Ambush.Util.loadedModules[path] && Ambush.Util.loadedModules[path] >= version) return false;
	var transport = Ajax.getTransport();

//	alert(path);
//	transport.open('GET', Ambush.Util.pathToUrl(path, version), false);
	transport.open('GET', path, false);
	transport.send(null);
	
//	alert(code);

	var code = transport.responseText;
	(typeof execScript != 'undefined') ? execScript(code) : 
		(Ambush.Util.context.eval ? Ambush.Util.context.eval(code) : eval(code));

	return true;
}
Ambush.Util.load = Ambush.Util.include;

/**
 * @param {String} newClass
 * @param {Object} superClass
 * @param {Object} props
 */
Ambush.Util.extend = function(newClass, superClass, props) {
	var multiple = [];
	if(superClass instanceof Array || typeof superClass == 'array') {
		multiple = superClass;
		superClass = multiple.shift();
	}
	if(typeof newClass == 'string') {
		newClass = Ambush.Util.evalPath(newClass, null, Ambush.Util.createClass(), 1);
	} else {
		return;
	}
	
	if(superClass) {
		var inheritance = function() {};
		inheritance.prototype = superClass.prototype;
		
		newClass.prototype = new inheritance();
		newClass.superClass = superClass.prototype;
	}	 
	for(var i = 0; i < multiple.length; i++) {
		Object.extend(newClass.prototype, multiple[i].prototype);
	}
	newClass.mixins = multiple;
	
	Object.extend(newClass.prototype, props || {});
	
	newClass.prototype.constructor = newClass;
}
Ambush.Util.define = Ambush.Util.extend;

Ambush.Util.createClass = function() {
    return function() {
		var _this = arguments.callee.prototype;
		_this.init.apply(this, arguments);
		for(var i = 0, mixins = _this.constructor.mixins, length = mixins.length; i < length; i++){
			mixins[i].init.apply(this);
		}
    }
}

Ambush.Util.hasOwnProperty = function(obj, prop) {
        if (Object.prototype.hasOwnProperty) {
            return obj.hasOwnProperty(prop);
        }
        
        return typeof obj[prop] != 'undefined' && 
                obj.constructor.prototype[prop] !== obj[prop];
}

Ambush.Util.dump = function(text){};
Ambush.Util.error = function(text){};

/////////////////////////////////////////////////////////////////////////////////
// file: ./ambush/Observable.js
/////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////////
// Управление событиями.
//

Ambush.Observable = Class.create({
	initialize: function() {
		this.aObservers = [];
	},
	
	attachObserver : function(sEventType,	mObserver) 
	{
		if(!(mObserver instanceof Object)) {
			return;
		}
		
		if(!this.aObservers[sEventType]) {
			this.aObservers[sEventType] = [];
		}
		
		this.aObservers[sEventType].push(mObserver);
	},
		
	detachObserver : function(sEventType, mObserver)
	{
		if(this.aObservers[sEventType] && this.aObservers[sEventType].contains(mObserver)) {
			this.aObservers[sEventType].remove(mObserver);
		}
		
	},
			
	notify : function(sEventType) 
	{
		if(!this.aObservers[sEventType]) {
			return;
		}
		
		for(var i = 0, aObservers = this.aObservers[sEventType], iLength = aObservers.length; i < iLength; i++) {
			
			if(aObservers[i] instanceof Function) {
				aObservers[i](
				sEventType,
				this
			);
			}
			else if(aObservers[i].update instanceof Function) {
				aObservers[i].update(
				sEventType,
				this
			);
			}
		}
	}
	
});

/**
 * Объект отвечающий за общие события в браузере.
 */
Ambush.events = new Ambush.Observable();

// Перечислим несколько зарание известных событий.
Ambush.EVENT_MAP_LOADED = 'EVENT_MAP_LOADED';
Ambush.EVENT_MAP_AREA_CHANGED = 'EVENT_MAP_AREA_CHANGED';



/////////////////////////////////////////////////////////////////////////////////
// file: ./ambush/MapPointCore.js
/////////////////////////////////////////////////////////////////////////////////

/**
 * Общий вьювер для точек на карте.
 * 
 * Пример использования:
 * mapPointViewer = new MapPointViewer(map);
 * point = {
 *	id: 913;
 *	infoWindowHtml: "что нибудь",
 *	caption: "что нибудь",
 *	imageURL: "урл к картинке",
 *	zoomLevel: 1,
 *	latitude: 58.000, 
 *	longitude: 58.000 
 * }
 * 
 * mapPointViewer.addPoint(point);
 * mapPointViewer.removePoint(913);
 */
Ambush.MapPointViewer = Class.create({
	points: [],
	hidden: true,
	initialize: function(map) {
		Ambush.Util.include("/js/markermanager.js");
		Ambush.Util.module("/js/markermanager.js");

		var mgrOptions = { borderPadding: 50}; //, maxZoom: 15, trackMarkers: true
		this.markerManager = new MarkerManager(map, mgrOptions);
		this.map = map;
		this.points = new Array();
		
	},
	toggle: function() {
		if( this.hidden == false )
			this.hide();
		else
			this.show();
  },
	getPointById: function(id)
	{
		var result = null;

		this.points.each( function(val)
		{ 
			if( val.id == id ) 
				result = val;
		});

		return result;
	},
	
	/**
   * Возвращает массив всех точек хранимых во вьювере.
   */
	getPoints: function()
	{
		return this.points;
  },

	show: function() {
		var thisObj = this;	
		this.hidden = false;
		// Перерисуем точки
		this.points.each( function(val){ thisObj.repaintPOI(val) })
  },
	hide: function() {
		var thisObj = this;	
		this.hidden = true;
		// Перерисуем точки
		this.points.each( function(val){ thisObj.repaintPOI(val) })
  },
	repaintPOI: function(point)
	{
		if( this.hidden == false )
		{
			if(point.hidden == true)
			{
				this.markerManager.addMarker(point.marker, point.zoomLevel);
				point.hidden = false;
			}
		}
		else
		{
			if(point.hidden == false)
			{
				this.markerManager.removeMarker(point.marker);
				//point.marker.remove();
				point.hidden = true;
			}
		}
	},
	
	getMenu: function(point)
	{
		var html = "";
		i = 0;
		jQuery.each(Ambush.MapMenu.items, function(key, item)
		{
			if( item.getItemType(null, point.marker) == "context" && item.isRendered(null, point.marker ) == true )
			{
				if( i == 0)
					html += "<div style='margin-top: 15px; margin-bottom: 5px; border-top: black solid 1px'></div><div class='baloon'><lu>";
				i++
				html += '<li><a href="'+this.getLink(point, point.marker)+'">'+this.getCaption(null, point.marker)+'</a></li>';
			}
		});
		html += "</lu></div>" 

		return html;
  },

	/**
   * Устанавливает новые дынные для вьювера.
   */
	setData: function(data)
	{
		var thisObj = this;	
		var newPoints = Array();
		// Удалим устаревшие точки.
		this.points.clone().each( function(oldPoint)
		{ 
			var poi = null;
			data.each( function(val){ 
				if( val.id == oldPoint.id ) {poi = val;} 
			});

			if(poi == null)
			{
				thisObj.markerManager.removeMarker(oldPoint.marker);
				//oldPoint.marker.remove();
				thisObj.points.without(oldPoint);
			}
			else
			{
				newPoints.push(oldPoint);
			}
		});
		this.points = newPoints;
		
		// Создадим новые точки, и если необходимо изменим данные у старых.
		data.each( function(val)
		{  
			var poi = thisObj.getPointById(val.id);
			if( poi == null )
			{
				poi = thisObj.createPoint(val);
				poi.marker.bindInfoWindowHtml(poi.infoWindowHtml + thisObj.getMenu(poi));

				thisObj.points.push(poi);
			}
			else
			{
				thisObj.refreshPoint(poi,val);
      }
		})

		// Перерисуем точки
		this.points.each( function(point){ thisObj.repaintPOI(point) });
  },
	
	/**
   * Добавляет точку к уже существующему массиву точек.
   */
	addPoint: function(newPoint)
	{
		var thisObj = this;	
		var point = this.getPointById(newPoint.id);
		if( point == null )
		{
			point = thisObj.createPoint(newPoint);
			this.points.push(point);
		}
		else
		{
			thisObj.refreshPoint(point, newPoint);
    }
	// Перерисуем точки
		this.points.each( function(point){ thisObj.repaintPOI(point) });
  },
	
	/**
   * Удаляет точку из массива.
   */
	removePoint: function(id)
	{
		var thisObj = this;	
		var newPoints = Array();
		// Удалим устаревшие точки.
		this.points.clone().each( function(oldPoint)
		{ 
			if(oldPoint.id == id)
				thisObj.markerManager.removeMarker(oldPoint.marker);
				//oldPoint.marker.remove();
			else
				newPoints.push(oldPoint);
		});
		//
		this.points = newPoints;
  },
	
	createPoint: function(data)
	{
		var poi = data;
		var point = new GLatLng(poi.latitude, poi.longitude);
		var img = new GIcon(); 
		img.image = poi.imageURL;

		if(poi.imageWidth != null && poi.imageHeight != null )
			img.iconSize=new GSize(poi.imageWidth, poi.imageHeight);
//		img.iconAnchor=new GPoint(2,16);
//		img.infoWindowAnchor=new GPoint(8,8);
		img.iconAnchor=new GPoint(0,0);
		img.infoWindowAnchor=new GPoint(0,0);
		
		var markerOptions ={icon:img, title: poi.caption};
		var marker = new GMarker(point,markerOptions);
		marker.bindInfoWindowHtml(poi.infoWindowHtml);
		
		poi.marker = marker;
		poi.hidden = true;
		
		return poi;
  },
	
	refreshPoint: function(poi, newData)
	{
		if( poi.infoWindowHtml != newData.infoWindowHtml )
		{
			poi.infoWindowHtml = newData.infoWindowHtml;
			poi.marker.bindInfoWindowHtml(poi.infoWindowHtml + this.getMenu(poi));
    }

		if( poi.imageURL != newData.imageURL )
		{
			poi.imageURL = newData.imageURL;

			var img = poi.marker.getIcon();
			img.image = poi.imageURL;
    }

		if( poi.longitude != newData.longitude ||  poi.latitude != newData.latitude)
		{
			poi.longitude = newData.longitude;
			poi.latitude = newData.latitude;
			var point = new GLatLng(poi.latitude, poi.longitude);

			poi.marker.setPoint(point);
		}

  }
});

/**
 * Общий контролер для точек на карте.
 */
Ambush.MapPointControler = Class.create({
	points: [],
	viewer: null,
	checkBoxId: null,
	imgId: null,
	
	initialize: function(requestURL, timeRefresh) 
	{
		var thisObj = this;	

		this.map = map;
		this.timeRefresh = timeRefresh;
		this.hidden = false;
		this.requestURL = requestURL;

		// Повешаем обработчик события на чек бокс, если этот чек-бокс указан.
		if( this.checkBoxId != null )
		{
			jQuery(this.checkBoxId).click(
					function () {
						thisObj.toggle();
					}
			);
		}

		var checked = this.restoreState();
		if(checked == "true")
		{
			this.show();
		}
		else
			this.hide();

		if( map == null )
			Ambush.events.attachObserver(Ambush.EVENT_MAP_LOADED, function(){ thisObj.onMapLoad() });
		//	setTimeout( function(){ thisObj.waitLoadingMap() }, 1000);
		else
			this.onMapLoad();
	},
	
	/**
   * Метод обновляет содержимое модели, при это крутит лоадером, что и отличает 
   * этот от метода load().
   */
	refresh: function() 
	{
		if( !this.viewer )
			return;
		
		if(!this.isHidden())
			this.show();
	},
	
	/**
   * Событие на закрузку карты.
   */
	onMapLoad: function() 
	{
		
	},
	
	// Метод устанавливает вьювер.
	setViewer: function(viewer)
	{
		this.viewer = viewer;

		var checked = this.restoreState();
		if(checked == "true")
			this.show();
		else
			this.hide();
  },
	
	toggle: function() {
		var checked = this.restoreState();
		if( checked == "true" )
			this.hide();
		else
			this.show();
  },
	
	show: function() {
		// Если чек бокс указан, его нужно включить.
		if( this.checkBoxId != null )
		{
			var resutl = jQuery(this.checkBoxId);
			if( resutl.length > 0 )
				resutl[0].enabledCheckBox();
		}
		this.setState("true");

		if( this.viewer != null )
		{
			this.viewer.show();
			if( this.imgId != null )
				jQuery(this.imgId).show();
			this.load();
		}
  },
	
	hide: function() {
		// Если чек бокс указан, его нужно выключить.
		if( this.checkBoxId != null )
		{
			var resutl = jQuery(this.checkBoxId);
			if( resutl.length > 0 )
				jQuery(this.checkBoxId)[0].disabledCheckBox();
		}
		
		this.setState("false");
		if( this.viewer != null )
			this.viewer.hide();

  },
	
	isHidden: function()
	{
		return this.viewer.hidden;
  },
	
	/***
   * Получает точку по ID
   */
	getPointById: function(id)
	{
		return this.viewer.getPointById(id);
	},

	/**
	 * Инициирует загрузку контента.
	 */
	load: function() {
		var thisObj = this;		

//	jQuery.get(requestURL, function(data,status){ thisObj.dataReady(data,status); } );
		new Ajax.Request(this.requestURL,{
			method: 'get',
			onSuccess: function(respunse) {
				thisObj.dataReady(respunse.responseJSON);
			},
			onComplete: function(respunse) {
				if( thisObj.imgId != null )
					jQuery(thisObj.imgId).hide();
			}
		});
  },

	dataReady: function(data)
	{
		var thisObj = this;
//		alert(Object.toJSON(data));
		this.viewer.setData(data);

		if( this.timeRefresh != 0 )
			setTimeout( function(){ thisObj.load() }, this.timeRefresh);
	},

	/**
   * Возвращает состояние видимости объектов при создании менеджера.
   */
	restoreState: function()
	{
		return "true";
  },
	
	/**
	 * "Абстрактный" метод, необходимо переопределить если нужно сохранять 
	 * состояние.
	 */
	setState: function(state)
	{
		
  }
	
	
});



/////////////////////////////////////////////////////////////////////////////////
// file: ./ambush/BBToolbar.js
/////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////
// Различный функционал для Би-Би панели...
//

Ambush.BBToolbar = {};

/**
 * Вставляет просто таг в указаную текстарею.
 */
Ambush.BBToolbar.insertSimpleTags = function(tag_name, textareaId)
{
	Ambush.BBToolbar.insertTags('[' + tag_name + ']', '[/' + tag_name + ']',textareaId);
};

/**
 * Вставляет лубой текст вокруг выделеного в текстарее.
 */
Ambush.BBToolbar.insertTags = function(begin, end, textareaId) 
{
	textareaElement = document.getElementById(textareaId);
  Ambush.BBToolbar.surroundText(begin, end, textareaElement);
};

/**
 * Вставляет смайлики в текст.
 */
Ambush.BBToolbar.insertSmile = function(smile, textareaId)
{
	textareaElement = document.getElementById(textareaId);
	Ambush.BBToolbar.surroundText(smile, '',textareaElement);
}

/**
 * Surrounds the selected text with text1 and text2.
 */
Ambush.BBToolbar.surroundText = function(text1, text2, textarea) {

	if (typeof(textarea.caretPos) != "undefined" && textarea.createTextRange) {
		var caretPos = textarea.caretPos, temp_length = caretPos.text.length;
		caretPos.text = caretPos.text.charAt(caretPos.text.length - 1) == ' ' ? text1 + caretPos.text + text2 + ' ' : text1 + caretPos.text + text2;

		if (temp_length == 0) {
			caretPos.moveStart("character", -text2.length);
			caretPos.moveEnd("character", -text2.length);
			caretPos.select();
		}
		else
			textarea.focus(caretPos);
	}
	// Mozilla text range wrap.
	else if (typeof(textarea.selectionStart) != "undefined") {
		var begin = textarea.value.substr(0, textarea.selectionStart);
		var selection = textarea.value.substr(textarea.selectionStart, textarea.selectionEnd - textarea.selectionStart);
		var end = textarea.value.substr(textarea.selectionEnd);
		var newCursorPos = textarea.selectionStart;
		var scrollPos = textarea.scrollTop;

		textarea.value = begin + text1 + selection + text2 + end;

		if (textarea.setSelectionRange) {
			if (selection.length == 0)
				textarea.setSelectionRange(newCursorPos + text1.length, newCursorPos + text1.length);
			else
				textarea.setSelectionRange(newCursorPos, newCursorPos + text1.length + selection.length + text2.length);
			textarea.focus();
		}
		textarea.scrollTop = scrollPos;
	}
	// Just put them on the end, then.
	else {
		textarea.value += text1 + text2;
		textarea.focus(textarea.value.length - 1);
	}
};


/////////////////////////////////////////////////////////////////////////////////
// file: ./ambush/FriendsPositionManager.js
/////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////
// Вывод друзей на карту.
//

Ambush.FriendsPositionManager = Class.create(Ambush.MapPointControler,{
	initialize: function($super, timeRefresh) {
		Ambush.FriendsPositionManager.instance = this;
		//	var thisObj = this;		
		var requestURL = "/index.php?widget=friendsposition";

		this.checkBoxId = "#chkbox_friends div.chkbox";
		this.imgId = "#chkbox_friends td.ajax_loader img";

		$super(requestURL, timeRefresh);
	},

	onMapLoad: function() 
	{
		var viewer = new Ambush.UsersPositionViewer(map);
		this.setViewer(viewer);
	},

	restoreState: function()
	{
		var result = Ambush.Util.getCookie("chkbox_friends");
		// Следаем по умолчанию галочку включенной
		if ( result == null )
			return "true";
		return result;
  },
	
	setState: function(state)
	{
		Ambush.Util.setCookie("chkbox_friends", state, 365*2);
	//	var result = Ambush.Util.getCookie("chkbox_friends");
		//alert(result);  
  }
});



/////////////////////////////////////////////////////////////////////////////////
// file: ./ambush/MapAreaManager.js
/////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////
// Управление переключением карты.
//
var prevMapArea;
var mapArea;

Ambush.MapAreaManager = new Object();

/**
 * Инициализирует менеджера. 
 */
Ambush.MapAreaManager.init = function()
{
	Ambush.events.attachObserver(Ambush.EVENT_MAP_LOADED, function(){
		GEvent.addListener(map, "moveend", function() {
			curPos=map.getCenter();
			minArea={square: 0};
			jQuery.each(mapAreaBounds,function(){
				if(curPos.lat()>this.minLat && curPos.lat()<this.maxLat && curPos.lng()>this.minLng && curPos.lng()<this.maxLng)
				{
					if(this.square<minArea.square || minArea.square==0)
					{
						minArea=this;
					}
				}
			});
			//autoArea=true;
			if(minArea.id != prevMapArea)
			{
				Ambush.SelectBox.setCurrentValue("mapAreaSelectBox",""+minArea.id);
				mapArea = minArea.id;
				Ambush.Util.setCookie('selectedMapArea', mapArea, 30);
				Ambush.events.notify(Ambush.EVENT_MAP_AREA_CHANGED);
				prevMapArea = minArea.id;
			}
			//alert(minArea.name);
		});
	});
}

/**
 * Устанавливает новую область видимости карты.
 */
Ambush.MapAreaManager.setMapArea = function()
{
		mapArea = Ambush.SelectBox.getCurrentValue("mapAreaSelectBox");
		prevMapArea = mapArea;

		action = new MapActions();
		listLatLng = action.getMapAreaBound(mapArea);

		if( mapWindow != null && mapWindow._minimised )
			mapWindow.normalised();

		if( map != null )
		{
			minLat=listLatLng[0];
			minLng=listLatLng[1];
			maxLat=listLatLng[2];
			maxLng=listLatLng[3];

			// Метод позиционирования карты в нужном городе.
			ne=new GLatLng(maxLat, maxLng);
			sw=new GLatLng(minLat, minLng);
			visibleBound=new GLatLngBounds(sw, ne);
			cntr=visibleBound.getCenter()
			zoom=map.getBoundsZoomLevel(visibleBound);
			map.setCenter(cntr,zoom);
			// Очередная реализация позиционирования карты (не удалять, может пригодится).
			//cntr = new GLatLng(minLat+(maxLat-minLat)/2, minLng+(maxLng-minLng)/2);
			//map.setCenter(cntr,10);
		}

		Ambush.Util.setCookie('selectedMapArea', mapArea, 365*2);
		Ambush.events.notify(Ambush.EVENT_MAP_AREA_CHANGED);
}




/////////////////////////////////////////////////////////////////////////////////
// file: ./ambush/MapManager.js
/////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////
// Управление и загрузка карты.
//
var map = null;

Ambush.MapState = function(){};
Ambush.MapState.prototype = {
	latitude: 0,
	longitude: 0,
	zoom: 1
}

Ambush.loadMaps = function() {
	google.load("maps", "2.s", {"callback" : Ambush.onLoadedMap});
}

Ambush.onLoadedMap = function () 
{
//	var mapState = new Ambush.MapState();
//	mapState.latitude = <?=$app->getUser()->getMapState()->latitude; ?>;
//	mapState.longitude = <?=$app->getUser()->getMapState()->longitude; ?>;
//	mapState.zoom = <?=$app->getUser()->getMapState()->zoom; ?>;
	Ambush.mapInitialize(map, null);
}

/**
 * Метод сохраняет состояние карты в куках.
 */
Ambush.setMapState = function(map) 
{
	if( map == null )
		return;

	var cntr = map.getCenter();
	var lat  = cntr.lat();
	var lng  = cntr.lng();
	var zoom = map.getZoom();
	var mapType = map.getCurrentMapType().getName();
	
	Ambush.Util.setCookie("map_lat",lat,365*2);
	Ambush.Util.setCookie("map_lng",lng,365*2);
	Ambush.Util.setCookie("map_zoom",zoom,365*2);
	Ambush.Util.setCookie("map_type",mapType,365*2);
}

/**
 * Метод востанавливает состояние карты из куков.
 */
Ambush.restoreMapState = function() 
{
	mapState = new	Ambush.MapState();
	mapState.latitude = Ambush.Util.getCookie("map_lat");
	mapState.longitude = Ambush.Util.getCookie("map_lng");
	mapState.zoom = Ambush.Util.getCookie("map_zoom");
	mapState.mapType = Ambush.Util.getCookie("map_type");
	
	if( mapState.latitude == null )
		mapState.latitude = 55.75;
	if( mapState.longitude == null )
		mapState.longitude = 37.62;
	if( mapState.zoom == null )
		mapState.zoom = 10;
	
	if( mapState.mapType == null )
		mapState.mapType = G_NORMAL_MAP.getName();

	mapState.zoom = parseInt(mapState.zoom);
	mapState.latitude = parseFloat(mapState.latitude);
	mapState.longitude = parseFloat(mapState.longitude);

	return mapState;
}

/**
 * Метод инициализирует карту после её загрузкию.
 */
Ambush.mapInitialize = function (mapState) 
{
	if (GBrowserIsCompatible()) 
	{
		map = new GMap2(document.getElementById("map"));
		map.addControl(new GLargeMapControl());
		map.addControl(new GMapTypeControl());
		
		if( mapState == null)
			mapState = Ambush.restoreMapState();
		var lat = mapState.latitude;	
		var lng = mapState.longitude;
		var zoom = mapState.zoom;
		map.setCenter(new GLatLng(lat,lng), zoom);

		if( mapState.mapType == G_SATELLITE_MAP.getName() )
			map.setMapType(G_SATELLITE_MAP);
		else if( mapState.mapType == G_HYBRID_MAP.getName() )
			map.setMapType(G_HYBRID_MAP);
		else
			map.setMapType(G_NORMAL_MAP);

		map.enableGoogleBar();

		//hookEvent('map', 'mousewheel', MouseWheel);
		// Включение зума на карте.
		map.enableScrollWheelZoom();
	}

	Ambush.events.notify(Ambush.EVENT_MAP_LOADED);

	// Повешаем событие на размера окна в котором содержится карта.
	if( mapWindow )
	{
		mapWindow.attachObserver(Ambush.MapWindow.MAXISED_EVENT, function(){ map.checkResize();	});
		mapWindow.attachObserver(Ambush.MapWindow.NORMALISED_EVENT, function(){ map.checkResize(); });
	}
}





/////////////////////////////////////////////////////////////////////////////////
// file: ./ambush/MapMenu.js
/////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////
// Инициализация и создание меню.
//

/**
 * Класс отвечающий за каждый пункт меню. 
 */
Ambush.MapMenuItem = Class.create(
{
	initialize: function() {
		this._itemType = "context";
		this._name = "";
		this._caption = "";
		this._link = null;
		this._overlay = null;
		this._action = null;
	},

	setItemType: function( type ) {
		this._itemType = type;
	},
	
	/**
   * Возвращает тип пункта меню.
   * 
   * Пока у пункта могут быть два типа:
   * - "context" - это значит что пункт должен показыватья в контекстном меню
   *						   на карте.
   * - ...			 - означает что пункт отображается в балуне.
   */
	getItemType: function(point, overlay) {
		return this._itemType;
	},

	setName: function( name ) {
		this._name = name;
	},
	
	/**
   * Должно возвращает название пункта меню на английском языке.
   */
	getName: function(point, overlay) {
		return this._name;
	},
	
	/**
   * Устанавливает заголовок меню.
   */
	setCaption: function( caption ) {
		this._caption = caption;
	},
	
	/**
   * Возвращает название пункта меню.
   */
	getCaption: function(point, overlay) {
		return this._caption;
	},
	
	/**
   * Устанавливает действие для данного меню.
   */
	setAction: function(action) {
		this._action = action;
	},
	
	/**
   * Действие выполняемые при нажатии на пункт меню.
   */
	action: function(point, overlay)
	{
		if( this._action != null )
			this._action(point, overlay);
		
		return null;
	},
	
	/**
   * Устанавливает ссылку по которой должен переходить браузер пир нажатии
   * на пункт меню.
   */
	setLink: function( link ) {
		this._link = link;
	},
	
	/**
   * Ccылка при нажатии ка которую должно выполниться определенное действие.
   */
	getLink: function(point ,overlay) {
		return this._link;
	},
	/**
   * Метод устанавливает оверлей при котором необходимо прорисовывать меню.
   */
	
	setOverlay: function(overlay) {
		this._overlay = overlay;
	},

	/**
   * Метод говорит нужно ли прорисовывать пункт меню для данного оверлея.
   */
	isRendered: function(point, overlay) {
		if( overlay == this._overlay )
			return true;
	
		return false;
	},
	
	render: function(point, overlay) {
		var result = "";
		if( this.getLink() != null )
			result += '<li><a href="'+this.getLink(point, overlay)+'">'+this.getCaption(point, overlay)+'</a></li>';
		else
		{
			result += '<li id="'+this.getName(point, overlay)+'"><a href="#">'+this.getCaption(point, overlay)+'</a></li>';		
    }
		return result;
	}
});

/**
 * Меню на карте, вот.
 */
Ambush.MapMenu = {};
/**
 * Список элементов меню.
 * 
 * Список свойств пункта меню:
 * - getName()
 * - getItemType(point, overlay)
 * - getCaption(point, overlay)
 * - getLink(point, overlay)
 * - isRendered(point, overlay)
 */
Ambush.MapMenu.items = new Array();

/**
 * Метод создает меню на карте.
 */
Ambush.MapMenu.initialize = function(){
	
	GEvent.addListener(map, "click", Ambush.MapMenu.mapLeftClick );
	GEvent.addListener(map, "singlerightclick", Ambush.MapMenu.hide ); 
	GEvent.addListener(map, "move", Ambush.MapMenu.hide );

//	jQuery("#map_menu").append(res);

};
	
Ambush.MapMenu.hide = function ()
{
	jQuery("#map_menu").hide(150)
};
	
/**
 * Событие на клик по левой клавише мыши на карте.
 */
Ambush.MapMenu.mapLeftClick = function (overlay, latlng, overlaylatlng) 
{
	jQuery("#map_menu").hide();
	if( overlay != null		)
		return;

	var src = null;
	var x = map.fromLatLngToContainerPixel(latlng).x;
	var y = map.fromLatLngToContainerPixel(latlng).y;

	var p=document.getElementById('map'); //пункт меню от которого мерять позицию
	var m=document.getElementById('map_menu'); //меню которое нужно показать
	var px=0;
	var py=0;

	px+=p.offsetLeft;
	py+=p.offsetTop;
	p=p.offsetParent;

//			m.style.left=(x+px-5)+'px';
//			m.style.top=(y+py-5)+'px';
	m.style.left=(x+px)+'px';
	m.style.top=(y+py)+'px';

	jQuery("#map_menu ul").html("");
	i=0;

	var point = {};
	point.x = x;
	point.y = y;
	
	jQuery.each(Ambush.MapMenu.items, function(key, item)
	{
		if( item.getItemType(point, overlay) == "context" && item.isRendered(point, overlay) == true )
		{
			var res = item.render(point, overlay)
			jQuery("#map_menu ul").append(res);
			
			if( item.getLink() == null )
			{
				jQuery("#"+item.getName(point, overlay)).click( function()
				{
					Ambush.MapMenu.hide();
					item.action(point, overlay);
				});
			}
		}
	});

	if(jQuery('#map_menu ul li').length > 0)
	{
		jQuery("#map_menu").show(150);
	}
}



/////////////////////////////////////////////////////////////////////////////////
// file: ./ambush/MapWindows.js
/////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////
// Наборы POI
//
var mapWindow = null;

Ambush.MapWindow = Class.create(Ambush.Observable,{
	initialize: function($super, name) {
		$super();
		var thisObj = this;
		this.children = [];
		
		this.caption = "";
		this.name = name;
		this.animationSpeed = 150;
		
		jQuery.each(jQuery.browser, function(i, val) 
		{
			if( i == "msie" && val == true)
				 thisObj.animationOff();
		});

		// Создаем пустой шаблон.
		this.windowContainer = document.createElement("div");
		this.windowContainer.setAttribute("class","windowContainer");
		if( name != null )
			this.windowContainer.setAttribute("id",name);

		this.contentContainer = document.createElement("div");
		this.contentContainer.setAttribute("class","contentContainer");
		this.windowContainer.appendChild(this.contentContainer);
		
		this.windowContainer.mapWindow = this;
		
		this._closed = false;
		this._minimised = false;
		this._maximised = false;
		this._normalised = true;
	
		this._normalised = true;
	
		this.buttons = {"close": false, "minised": false ,"maximised": false};
	},
	
	/**
   * Находит среди подчиненных окон, окно с нужным именем, 
   */
	getWindowByName: function(name) 
	{
		if(name == null)
			return null;
		if(name == "")
			return null;
			
		var result = null
		jQuery.each(this.children, function(i, val) 
		{
			if( val.name == name )
			{
				result = val;
				return;
      }
		});
		
		return result;
	},
	
	/**
   * Метод выключает анимацию окон.
   */
	animationOff: function() {
		this.animationSpeed = 0;
	},
	
	setCaption: function(caption) {
		this.caption = caption;
    jQuery(this.windowContainer).find(".captionText").html(this.caption);
	},
	
	setHTML: function(html) 
	{
		this.content = html;
		//this.contentElement = null;
    jQuery(this.windowContainer).find(".contentContainer").html(this.content);
	},
	
	/**
   * Метод включет индикатор загрузки в заголовке окна.
   */
	ajaxLoaderOn: function() 
	{
    jQuery(this.windowContainer).find(".ajax-loader").show();		
  },	
	
	/**
   * Метод выключает индикатор загрузки в заголовке окна.
   */
	ajaxLoaderOff: function() 
	{
    jQuery(this.windowContainer).find(".ajax-loader").hide();		
  },
	/**
   * Метод загружает содержимое окна с указанного урла.
   */
	setURL: function(url) 
	{
		var thisObj = this;	
		thisObj.ajaxLoaderOn();
		new Ajax.Request(url,{
			method: 'get',
			onSuccess: function(respunse) {
				thisObj.setHTML(respunse.responseText);
			},
			onComplete: function() {
				thisObj.ajaxLoaderOff();
			},
			onFailure: function(){
				thisObj.setHTML("Произошла ошибка при загрузке содержимого окна с сервера.");
      }
		});
	},
	
	setElement: function(element) 
	{
		this.setHTML("");
		this.contentElement = element;
		if(this.contentContainer != null)
		{
			this.contentContainer.appendChild(this.contentElement);
			jQuery(this.contentElement).show();
		}

	},
	
	addWindow: function( window, order ) 
	{
		// Проверим существование окна с подобным именем.
		var oldWindow = this.getWindowByName(window.name); 
		if( oldWindow )
		{
			oldWindow.close(true);
			var thisObj = this;	
			setTimeout( function(){ thisObj.addWindow(window, order) }, this.animationSpeed+100);
		}
		else
		{
			window.parent = this;
			this.children.push(window);
			if( this.contentContainer != null )
				window.draw(this.contentContainer, order);
		}
  },
	
	setPrototype: function(prototype) 
	{
		var thisObj = this;	
		this.windowContainer.innerHTML = prototype.innerHTML;
    
		jQuery(this.windowContainer).find(".captionText").html(this.caption);
		this.contentContainer = jQuery(this.windowContainer).find(".contentContainer")[0];
		
		if( this.contentContainer != null )
		{
			if( this.contentElement == null )
				jQuery(this.windowContainer).find(".contentContainer").html(this.content);
			else
			{
				if(this.contentContainer != null)
				{
					this.contentContainer.appendChild(this.contentElement);
					jQuery(this.contentElement).show();
				}
			}
		}
		jQuery(this.windowContainer).find(".caption").dblclick( function(){
			if( !thisObj._minimised )
				thisObj.minimised();
			else
				thisObj.normalised();
		});
		
		jQuery(this.windowContainer).find(".closeButton").click( function(){
			thisObj.close(true);
		});

		jQuery(this.windowContainer).find(".minisedButton").click( function(){
			thisObj.minimised();
		});
		
		jQuery(this.windowContainer).find(".maximisedButton").click( function(){
			thisObj.maximised();
		});
		
		jQuery(this.windowContainer).find(".normalButton").click( function(){
			thisObj.normalised();
		});

		this.showButton();
	},
	
	// Метод включает кнопки в заголовке окна.
	enabledButton: function(button)
	{
		this.buttons[button] = true;
  },

	// Метод выключает кнопки в заголовке окна.
	disabledButton: function(button)
	{
		this.buttons[button] = false;
  },
	
	showButton: function() 
	{
		if( this.buttons["close"] == true )
			jQuery(this.windowContainer).find(".closeButton").show();
		else
		{
			jQuery(this.windowContainer).find(".closeButton").css("display","none");
		}
		if( this.buttons["minised"] == true )
			jQuery(this.windowContainer).find(".minisedButton").show();
		else
		{
			jQuery(this.windowContainer).find(".minisedButton").css("display","none");
//			jQuery(this.windowContainer).find(".minisedButton").hide();
		}
		if( this.buttons["maximised"] == true )
			jQuery(this.windowContainer).find(".maximisedButton").show();
		else
		{
			jQuery(this.windowContainer).find(".maximisedButton").css("display","none");
//			jQuery(this.windowContainer).find(".maximisedButton").hide();
		}
		jQuery(this.windowContainer).find(".normalButton").css("display","none");
		
		if( this._normalised == true )
		{
			jQuery(this.windowContainer).find(".normalButton").hide();
    }
		else if( this._minimised == true )
		{
			jQuery(this.windowContainer).find(".normalButton").show();
			jQuery(this.windowContainer).find(".minisedButton").hide();
    }
		else if( this._maximised == true )
		{
			jQuery(this.windowContainer).find(".normalButton").show();
			jQuery(this.windowContainer).find(".maximisedButton").hide();
    }

	},
		
	draw: function( parentElement, order) {
		this.parentElement = parentElement;
		if( order != null )
		{
			var refnode = null;
	    var childNodes = this.parentElement.childNodes;

			for( var i = 0; i < childNodes.length; i++ )
	    {
				var itemElement = childNodes[i];
				if( itemElement.tagName && order == i)
				{
					refnode = itemElement;
					break;
        }
	    }
		
			if( refnode != null )
				parentElement.insertBefore(this.windowContainer, refnode);
			else
				parentElement.appendChild(this.windowContainer);
    }
		else
		{
			parentElement.appendChild(this.windowContainer);
		}
		jQuery(this.windowContainer).hide();
		jQuery(this.windowContainer).slideDown(this.animationSpeed);
//		alert(jQuery(this.windowContainer).find(".captionText").html());
	},
	
	/**
   * Метод скрывает окно.
   */
	hide: function() 
	{
		jQuery(this.windowContainer).hide();
	},
	
	/**
   * Метод отображает окно.
   */
	show: function() 
	{
		jQuery(this.windowContainer).show();
	},
	
	/**
   * Возвращает колличество дочерних окон.
   */
	getChildrenCount: function()
	{
//	  var childNodes = this.contentContainer.childNodes;
		return this.children.length;
	},
	/**
   * Возвращает true если окно закрыто.
   */
	isClosed: function()
	{
		return this._closed;
	},
	/**
   * Изменяет размер окна.
   */
	resize: function(height)
	{
		if( this.contentContainer != null )
			jQuery(this.contentContainer).height(height);
		if( this.contentElement != null )
			jQuery(this.contentElement).height(height);
		
	},
	
	/**
   *  Удаляет окно из контейнера.
   */ 
	removeWindow: function()
	{
		// Заодно удалим все дочерние окна.
		jQuery.each(this.children, function(i, val) 
		{
			val.close(false);
		});

		this.parentElement.removeChild(this.windowContainer);
	},
	/**
   *  Закрывает окно и очищает све необходимые ресурсы.
   */
	close: function( animation ) 
	{
		var thisObj = this;

		if( this._closed == false )
		{
			this._closed = true;
			this._minimised = false;
			this._maximised = false;
			this._normalised = false;
		
			if( this.animationSpeed > 0 && animation)
			{
				jQuery(this.windowContainer).slideUp(this.animationSpeed);
				setTimeout( function(){ thisObj.removeWindow() }, this.animationSpeed+100);
			}
			else
			{
				jQuery(this.windowContainer).hide();
				thisObj.removeWindow();
			}
		
			if( this.parent != null )
				this.parent.children = this.parent.children.without(this);

			this.parent = null;		

			// Посылаем сигнал о закрытии.
			this.notify(Ambush.MapWindow.CLOSE_EVENT);
		}
	},
	
	minimised: function() 
	{
		if( this.animationSpeed > 0 )
			jQuery(this.contentContainer).slideUp(this.animationSpeed);
		else
			jQuery(this.contentContainer).hide();

		this._closed = false;
		this._minimised = true;
		this._maximised = false;
		this._normalised = false;
		this.showButton();

		// Посылаем сигнал о сворачивании.
		this.notify(Ambush.MapWindow.MIMISED_EVENT);	
	},
	
	maximised: function() 
	{
		// Сохраним размер нормального окна.
		if( this.height == null )
			this.height = jQuery(this.contentContainer).height();
		
		var maxHeight = jQuery(window).height()-200;
		this.resize(maxHeight);
		
		if( this.animationSpeed > 0 )
			jQuery(this.contentContainer).slideDown(this.animationSpeed);
		else
			jQuery(this.contentContainer).show();
		
		this._closed = false;
		this._minimised = false;
		this._maximised = true;
		this._normalised = false;
		this.showButton();
		
		// Посылаем сигнал об увеличении.
		this.notify(Ambush.MapWindow.MAXISED_EVENT);
	},

	normalised: function() 
	{
		// Востановим нормальный размер окна если он был изменен.
		if( this.height != null )
			this.resize(this.height);
		
//		this.height = null;
		if( this.animationSpeed > 0 )
			jQuery(this.contentContainer).slideDown(this.animationSpeed);
		else
			jQuery(this.contentContainer).show();

		this._closed = false;
		this._minimised = false;
		this._maximised = false;
		this._normalised = true;
		this.showButton();
		// Посылаем сигнал о нормализации окна.
		this.notify(Ambush.MapWindow.NORMALISED_EVENT);	
	}
});

Ambush.getParentByClass = function (element, elementClass)
{
//	if(element.hasClass(elementClass))
	if(element.mapWindow != null)
	{
		return element;
	}
	else
	{
		var parent = jQuery(element).parent();
		if( parent.length > 0 )
			return Ambush.getParentByClass(parent.get(0),elementClass);
	
  }	
	return null;
}

Ambush.getMapWindow = function (element)
{
	var elementWindow = Ambush.getParentByClass(element,"windowContainer");

	if( elementWindow )
		return elementWindow.mapWindow;

	return null;
}

/**
* Список событий генерируемых окном.
*/
Ambush.MapWindow.MIMISED_EVENT		= "MIMISED_EVENT"; 
Ambush.MapWindow.MAXISED_EVENT		= "MAXISED_EVENT"; 
Ambush.MapWindow.NORMALISED_EVENT = "NORMALISED_EVENT"; 
Ambush.MapWindow.CLOSE_EVENT			= "CLOSE_EVENT"; 


/////////////////////////////////////////////////////////////////////////////////
// file: ./ambush/MessageManager.js
/////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////
// Управление списком сообщений.
//

Ambush.MessageManager = function(user_id,page){
	var thisObj = this;	
	this.user_id = user_id;
	this.page = page;
	setTimeout( function(){ thisObj.refreshMessageList() }, 5000);
}
/**
* Посылает запрос на сервер 
*/
Ambush.MessageManager.prototype.refreshMessageList = function()
{
	var thisObj = this;		

	var requestURL = "/index.php?widget=messagelist&user_id="+this.user_id+"&page="+this.page+"";

//	jQuery.get(requestURL, function(data,status){ thisObj.dataReady(data,status); } );
	new Ajax.Request(requestURL,{
  	method: 'get',
	  onSuccess: function(response) {
			thisObj.dataReady(response.responseText,response.statusText);
	  }
	});
}               
      
Ambush.MessageManager.prototype.dataReady = function(html,status)
{
	var thisObj = this;	
	if(html != null && html != "")
	{
		jQuery("#messageList").html(html);
	}
	setTimeout( function(){ thisObj.refreshMessageList() }, 5000);
}

/////////////////////////////////////////////////////////////////////////////////
// file: ./ambush/POIManager.js
/////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////
// Наборы POI
//

Ambush.POIViewer = Class.create(Ambush.MapPointViewer,{
	createPoint: function($super, data)
	{
		var poi = $super(data);
		poi.marker.objectID = poi.id;
		poi.marker.objectType ='dynPOI';
		
		var img = poi.marker.getIcon();
		img.iconSize = new GSize(16,16); 
		img.iconAnchor = new GPoint(8,8);
		img.infoWindowAnchor = new GPoint(8, 8); 

		return poi;
  }
});

Ambush.POITypeManager = Class.create(Ambush.MapPointControler,{
	initialize: function($super, type, mapAreaId) {
		Ambush.POIManager[type] = this;
		this.type = type;
		this.mapAreaId = mapAreaId;
		var requestURL = "/index.php?widget=poi&type="+this.type+"&mapArea="+this.mapAreaId;
		this.checkBoxId = "#chkbox_"+type+" div input";
		this.imgId = "#chkbox_"+type+" td.ajax_loader img";

		$super(requestURL, 0);
	},

	onMapLoad: function() 
	{
		var viewer = new Ambush.POIViewer(map);
		this.setViewer(viewer);
	},

	restoreState: function()
	{
		return Ambush.Util.getCookie("chkbox_"+this.type);
  },
	setState: function(state)
	{
		Ambush.Util.setCookie("chkbox_"+this.type,state,365*2);
  },
	
	/**
	 * Метод метод указывает менеджеру город, для которого требуется запрашивать
	 * POI.
	 */
	setMapAreaId: function(mapAreaId) {
		this.mapAreaId = mapAreaId;
		this.requestURL = "/index.php?widget=poi&type="+this.type+"&mapArea="+this.mapAreaId;
  },

	/**
	 * Обновляет набор POI с сервера.
	 */
	refreshPoint: function(id) {
		var thisObj = this;		
		var requestURL = "/index.php?widget=poi&id="+id;

		new Ajax.Request(requestURL,{
			method: 'get',
			onSuccess: function(respunse) {
				thisObj.refreshPointReady(respunse.responseJSON);
			}
		});
  },

	/**
	 * Обновляет только одну POI, в зависимости от структуры data.
	 */
	refreshPointReady: function(data)
	{
		this.viewer.addPoint(data);
	}
});

Ambush.POIManager = Class.create({

	/**
	 * Конструктору передается Id карты на которой следует вывести POI, период
	 * обновления задовать не нужно, так как пои загружаются только 1 раз.
	 * и больше их перезагружать не нужно.
	 */
	initialize: function(mapAreaId)
	{
		Ambush.POIManager.instance = this;
		this.types = ['camera','gas','carshop','tyres','carwash','service','parts','cafe','hotel','hospital','police'];
		this.types.each(function(type){                                                       
			new Ambush.POITypeManager(type, mapAreaId);
    });
		
		// Сгеним событие символизирующее успешный запуск менеджера.
		Ambush.events.notify(Ambush.EVENT_POI_MANAGER_LOADED);
	},
	getPointById: function(id)
	{
		var point = null;
		
		this.types.each(function(type){                                                       
			var p = Ambush.POIManager[type].getPointById(id);
			if( p )
				point = p;
    });
		return point;
	},
		
	/**
   * Обновление все POI
   */
	refresh: function() 
	{
		this.types.each(function(type){                                                       
			Ambush.POIManager[type].refresh();
    });
	},

	/**
   * Установим текущий город для всех типов POI
   */
	setMapAreaId: function(mapAreaId)
	{
		this.types.each(function(type){
			Ambush.POIManager[type].setMapAreaId(mapAreaId);
    });
	},
	
	/**
   * Обновляет указанную POI с сервера.
   */
	refreshPoint: function(id) 
	{
		this.types.each(function(type){                                                       
			var p = Ambush.POIManager[type].getPointById(id);
			if( p )
				Ambush.POIManager[type].refreshPoint(id);
    });
  }
});

/**
 * Список событий гененрируемых менеджером POI.
 */
Ambush.EVENT_POI_MANAGER_LOADED = 'EVENT_POI_MANAGER_LOADED';



/////////////////////////////////////////////////////////////////////////////////
// file: ./ambush/Rating.js
/////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////
// Управление рейтингами на карте.
//

/**
 * Процедура изменяет голос за определнный POI.
 */
Ambush.setPOIVote = function(poiId, vote)
{
//	var poi = Ambush.POIManager.instance.getPointById(poiId);
	var oldVote = parseInt(jQuery(".poiRating"+poiId+" .currentVoteValue").html());
	if( oldVote == vote )
		return;
	var delta = vote - oldVote;
	
	if( vote < 0 )
	{
		jQuery(".poiRating"+poiId+" span.voteMinus.deselectedState").hide();
		jQuery(".poiRating"+poiId+" span.voteMinus.selectedState").show();

		jQuery(".poiRating"+poiId+" span.votePlus.deselectedState").show();
		jQuery(".poiRating"+poiId+" span.votePlus.selectedState").hide();
  }
	else if( vote > 0 )
	{
		jQuery(".poiRating"+poiId+" span.votePlus.deselectedState").hide();
		jQuery(".poiRating"+poiId+" span.votePlus.selectedState").show();

		jQuery(".poiRating"+poiId+" span.voteMinus.deselectedState").show();
		jQuery(".poiRating"+poiId+" span.voteMinus.selectedState").hide();
	}
	
	var rating = parseInt(jQuery(".poiRating"+poiId+" .ratingValue").html());
	rating = rating + delta;
	if( rating < 0 )
	{
		jQuery(".poiRating"+poiId+" .ratingValue").removeClass("positiveRating");
		jQuery(".poiRating"+poiId+" .ratingValue").addClass("negativeRating");
  }
	else
	{
		jQuery(".poiRating"+poiId+" .ratingValue").removeClass("negativeRating");
		jQuery(".poiRating"+poiId+" .ratingValue").addClass("positiveRating");
  }
	
	var ratingString = "0";
	if( rating != 0)
		ratingString = rating;
	
	jQuery(".poiRating"+poiId+" .ratingValue").html(ratingString);
	jQuery(".poiRating"+poiId+" .currentVoteValue").html(vote);
	
	//Ambush.ratingRender(poiId);
	
	// Сменим голос.
	var action = new MapContextMenuActions();
	action.setPOIVote(poiId, vote);
	
	// Обновим пои с сервера.
	if( Ambush.POIManager.instance )
		Ambush.POIManager.instance.refreshPoint(poiId);
}

/*
Ambush.ratingRender = function(poiId)
{
	var poi = Ambush.POIManager.instance.getPointById(poiId);
	var selectedVoteMinus = "";
	var deselectedVoteMinus = "";
	var selectedVotePlus = "";
	var deselectedVotePlus = "";
	
	if( poi.vote < 0 )
	{
		selectedVoteMinus = "";
		deselectedVoteMinus = "style='display:none'";

		selectedVotePlus = "style='display:none'";
		deselectedVotePlus = "";
	}
	else	if( poi.vote > 0)
	{
		selectedVotePlus = "";
		deselectedVotePlus = "style='display:none'";

		selectedVoteMinus = "style='display:none'";
		deselectedVoteMinus = "";
	}
	else
	{
		selectedVotePlus = "style='display:none'";
		deselectedVotePlus = "";

		selectedVoteMinus = "style='display:none'";
		deselectedMinus = "";
	}
	var html = "	\
				<div style='float:left'>	\
					<span style='cursor:pointer;' onClick='Ambush.setPOIVote("+poi.id+",-1);' >	\
						<span class='vote1 selectedState' "+selectedVoteMinus+">	\
							<img  src='/img/icnFriends1.gif' width='15' height='15' border='0' hspace='4'>	\
						</span> \
						<span class='vote1 deselectedState' "+deselectedVoteMinus+">	\
							<img title='Опустить' src='/img/icnFriends0.gif' width='15' height='15' border='0' hspace='4'>	\
						</span>	\
					</span>	\
					<span class='ratingValue'>"+poi.rating+"</span>	\
					<span style='cursor:pointer;' onClick='Ambush.setPOIVote("+poi.id+",+1);'>	\
						<span class='vote3 selectedState' "+selectedVotePlus+">	\
							<img  src='/img/icnUserPOI1.gif' width='15' height='15' border='0' hspace='4'>	\
						</span>	\
						<span class='vote3 deselectedState' "+deselectedVotePlus+">	\
							<img title='Поднять' src='/img/icnUserPOI0.gif' width='15' height='15' border='0' hspace='4'>	\
						</span>	\
					</span>	\
				</div>	\
		";
	jQuery("#poiRating"+poiId).html(html);	
}
*/


/////////////////////////////////////////////////////////////////////////////////
// file: ./ambush/SelectBox.js
/////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////
// Полагин для создание кастом-селект-боксов
//

Ambush.SelectBox = new Object();
/**
 * Метод инициализирующий селест бокс.
 * 
 * Метод вешает обработчики событий, накладывает стили.
 * 
 * Параметры:
 * id - id dom-элемена;
 * currentItemIndex - индекст пекущего элемента;
 * callback - функция обратного вызова, вызывается при выборе пользователем 
 * какого либо пункта меню.
 *
 * Пример шаблона:
 *		<div id="mapAreaSelectBox" class="selectBox">
 *		  <div class="selectBoxContainer">
 *			  ........... Можно вставить что нибудь ............
 * 		 	  <div class="selectBoxValue">Москва</div>
 *		  </div>
 *  		<div class="selectBoxItems" style="display: none;">
 *				<div class="selectBoxItem">Пермь</div>
 *				<div class="selectBoxItem">Москва</div>
 *				<div class="selectBoxItem">Питер</div>
 *				<div class="selectBoxItem">Ебург</div>
 *			</div>
 *		</div>
 */
Ambush.SelectBox.init = function( id, currentItemIndex, callback)
{
	var query = jQuery("#"+id);
	query[0].callbackFunc = callback;
	query[0].mouseleave = false;

	// Повешаем обработчик на нажатие.
	query.find(".selectBoxContainer").click(function() {
		if(query.find(".selectBoxItems").css("display") == "none")
			query.find(".selectBoxItems").show();
		else
			query.find(".selectBoxItems").hide();
	});

	// Повешаем обработчик на выбор нужного значения.
	query.find(".selectBoxItem").click( function( object )
	{
		var selectedElement = this;
		query.find(".selectBoxItem").each( function( index, element )
		{
			if( selectedElement == element )
			{
				query.find(".selectBoxValue").html(element.innerHTML);
				query[0].currentItemIndex = currentItemIndex;
				query[0].currentItemValue = element.getAttribute("value");
				query[0].callbackFunc(index, element);
			}
		});
		query.find(".selectBoxItems").hide();
	});

	// Подставим текущее значение.
	Ambush.SelectBox.setCurrentIndex(id, currentItemIndex);

	query.bind("mouseleave",function()
	{
		this.mouseleave = true;
		setTimeout( function() {
			if( query[0].mouseleave == true )
				query.find(".selectBoxItems").hide();
		}, 500);
		
	});

	query.bind("mouseenter",function()
	{
		this.mouseleave = false;
	});
};

/**
 * Метод устанавливает новый текущий элемент.
 */
Ambush.SelectBox.setCurrentIndex = function( id, currentItemIndex )
{
	var query = jQuery("#"+id);

	// Подставим текущее значение.
	query.find(".selectBoxItem").each( function( index, element )
	{
		if( index == currentItemIndex )
		{
			query.find(".selectBoxValue").html(element.innerHTML);
			query[0].currentItemIndex = currentItemIndex;
			query[0].currentItemValue = element.getAttribute("value");
		}
	});
};

/**
 * Метод устанавливает новый текущий элемент, по его значению.
 */
Ambush.SelectBox.setCurrentValue = function( id, currentItemValue )
{
	var query = jQuery("#"+id);

// Подставим текущее значение.
	query.find(".selectBoxItem").each( function( index, element )
	{
		if( element.getAttribute("value") == currentItemValue )
		{
			query.find(".selectBoxValue").html(element.innerHTML);
			query[0].currentItemIndex = index;
			query[0].currentItemValue = element.getAttribute("value");
		}
	});
};

/**
 * Возвращает индекс текущего эдемента.
 */
Ambush.SelectBox.getCurrentIndex = function( id )
{
	var query = jQuery("#"+id);
	return query[0].currentItemIndex;
};

/**
 * Возвращает заначение атрибута "value" текущего эдемента.
 */
Ambush.SelectBox.getCurrentValue = function( id )
{
	var query = jQuery("#"+id);
	return query[0].currentItemValue;
};


/////////////////////////////////////////////////////////////////////////////////
// file: ./ambush/TrafficEventManager.js
/////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////
// Управление дорожными событиями.
//

Ambush.TrafficEventViewer = Class.create(Ambush.MapPointViewer,{
	createPoint: function($super,data)
	{
		var poi = $super(data);
		poi.marker.objectID = poi.id;
		poi.marker.objectType ='trafficEvent';
		
		var img = poi.marker.getIcon();
		img.iconSize = new GSize(16,16); 
		img.iconAnchor = new GPoint(8,8);
		img.infoWindowAnchor = new GPoint(8, 8); 

		return poi;
  }
});

Ambush.TrafficEventTypeManager = Class.create(Ambush.MapPointControler,{
	initialize: function($super, type, timeRefresh) {
		Ambush.TrafficEventManager[type] = this;
		var requestURL = "/index.php?widget=trafficevent&type="+type;
		this.checkBoxId = "#chkbox_"+type+" div input";
		this.imgId = "#chkbox_"+type+" td.ajax_loader img";
		this.type = type;

		$super(requestURL, timeRefresh);
	},

	onMapLoad: function() 
	{
		var viewer = new Ambush.TrafficEventViewer(map);
		this.setViewer(viewer);
	},

	restoreState: function()
	{
		return Ambush.Util.getCookie("chkbox_"+this.type);
  },
	setState: function(state)
	{
		Ambush.Util.setCookie("chkbox_"+this.type, state, 365*2);
  }
});
	
Ambush.TrafficEventManager = Class.create({
	initialize: function(timeRefresh) {
		Ambush.TrafficEventManager.instance = this;
		this.types = ['activAmbush','ambush','jam','crash','danger'];
		this.types.each(function(type){                                                       
			new Ambush.TrafficEventTypeManager(type, timeRefresh);
    });
	},
	
	getPointById: function(id)
	{
		var point = null;
		
		this.types.each(function(type){                                                       
			var p = Ambush.TrafficEventManager[type].getPointById(id);
			if( p )
				point = p;
    });
		return point;
	},
	
	/**
   * Обновление всех дорожных событий.
   */	
	refresh: function() 
	{

		this.types.each(function(type){                                                       
			Ambush.TrafficEventManager[type].refresh();
    });
	}
});



/////////////////////////////////////////////////////////////////////////////////
// file: ./ambush/UserPOIManager.js
/////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////////
// Управление метками пользователя.
//
Ambush.UsersPOIViewer = Class.create(Ambush.MapPointViewer,{
	createPoint: function($super,data)
	{
		var poi = $super(data);
		poi.marker.objectID = poi.id;
		poi.marker.objectType='userPOI';
		
		poi.marker.getIcon().iconAnchor=new GPoint(2,16); 
		poi.marker.getIcon().infoWindowAnchor=new GPoint(8,8);	

		return poi;
  }
});

Ambush.UserPOIManager = Class.create(Ambush.MapPointControler,{
	initialize: function($super, timeRefresh, defaultState) {
	//	var thisObj = this;
		Ambush.UserPOIManager.instance = this;
		var requestURL = "/index.php?widget=userspoi";
		this.defaultState = defaultState;
		this.checkBoxId = "#chkbox_places div.chkbox";
		this.imgId = "#chkbox_places td.ajax_loader img";

		$super( requestURL, timeRefresh);
	},
	onMapLoad: function() 
	{
		var viewer = new Ambush.UsersPOIViewer(map);
		this.setViewer(viewer);
	},
	
	restoreState: function()
	{
		if( this.defaultState != null )
			return defaultState;

		var result = Ambush.Util.getCookie("chkbox_places1");
		// Следаем по умолчанию галочку включенной
		if ( result == null )
			return "true";
		return result;
  },
	setState: function(state)
	{
		if( this.defaultState != null )
		{
			this.defaultState = state;
			return;
		}

		Ambush.Util.setCookie("chkbox_places1",state,365*2);
  }
});

/////////////////////////////////////////////////////////////////////////////////
// file: ./ambush/UserPositionManager.js
/////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////
// Одного определенного пользователя. Использует тот же вьювер MapPointViewer
// для вывода данных.
//

Ambush.UserPosition = Class.create(Ambush.MapPointControler,{
	initialize: function($super, userId, timeRefresh) {
		this.userId = userId;
		var requestURL = "/index.php?widget=userposition&user_id="+userId;

		$super(requestURL, timeRefresh);
	},

	onMapLoad: function()
	{
		var viewer = new Ambush.UsersPositionViewer(map);
		this.setViewer(viewer);
	},

	dataReady: function(data)
	{
		var thisObj = this;
//		alert(Object.toJSON(data));
		this.viewer.addPoint(data);

		if( this.timeRefresh != 0 )
			setTimeout( function(){ thisObj.load() }, this.timeRefresh);
	}
});

Ambush.UserPosition.ownPosition = null;


/////////////////////////////////////////////////////////////////////////////////
// file: ./ambush/UsersPositionManager.js
/////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////
// Вывод друзей на карту.
//

Ambush.UsersPositionViewer = Class.create(Ambush.MapPointViewer,{
	createPoint: function($super,data)
	{
		var poi = $super(data);
		poi.marker.objectID= poi.id;
		poi.marker.objectType='userAvatar';
		
		var img = poi.marker.getIcon();
		if(poi.imageWidth != null && poi.imageHeight != null )
		{
			img.iconSize = new GSize(poi.imageWidth, poi.imageHeight); 
			img.iconAnchor = new GPoint(0, poi.imageHeight);
			img.shadowSize = new GSize(poi.imageWidth+8, poi.imageHeight+8);
			img.infoWindowAnchor = new GPoint(poi.imageWidth, poi.imageHeight); 
		}
		else
		{
			img.iconSize = new GSize(32,32); 
			img.iconAnchor = new GPoint(0,32);
			img.shadowSize = new GSize(40, 40);
			img.infoWindowAnchor = new GPoint(32, 32); 
    }
		img.shadow= "/img/avatarShadowOnline.png";

		return poi;
  }
});

Ambush.UsersPositionManager = Class.create(Ambush.MapPointControler,{
	initialize: function($super, timeRefresh) {
		Ambush.UsersPositionManager.instance = this;
		//	var thisObj = this;		
		var requestURL = "/index.php?widget=usersposition";

		this.checkBoxId = "#chkbox_usersposition div.chkbox";
		this.imgId = "#chkbox_usersposition td.ajax_loader img";

		$super(requestURL, timeRefresh);
	},

	onMapLoad: function() 
	{
		var viewer = new Ambush.UsersPositionViewer(map);
		this.setViewer(viewer);
	},
	
	// Перегрузим метод load каждый раз при загрузке получать новые координаты
	// с карты.
	load: function($super) 
	{
		if( map.getZoom() >= 10 )
		{
			// Вычислим координыты окна в котором должны показываться пользователи.
			var bounds = map.getBounds();
			var dlan = bounds.getNorthEast().lat() - bounds.getSouthWest().lat();
			var dlng = bounds.getNorthEast().lng() - bounds.getSouthWest().lng();
			
			var $coordinate = {
				latitude1: bounds.getSouthWest().lat() - dlan,
				longitude1: bounds.getSouthWest().lng() - dlng,
				latitude2: bounds.getNorthEast().lat() + dlan,
				longitude2: bounds.getNorthEast().lng() + dlng
			};
			
			var query = Object.toQueryString($coordinate);
			this.requestURL = "/index.php?widget=usersposition&"+query;
			$super();
		}
		else
		{
			var thisObj = this;
			jQuery(this.imgId).hide();
			setTimeout( function(){ thisObj.load() }, this.timeRefresh );
    }
	},
	
	restoreState: function()
	{
		var result = Ambush.Util.getCookie("chkbox_usersposition");
		// Следаем по умолчанию галочку включенной
		if ( result == null )
			return "true";
		return result;
  },
	
	setState: function(state)
	{
		Ambush.Util.setCookie("chkbox_usersposition", state, 365*2);
	//	var result = Ambush.Util.getCookie("chkbox_friends");
		//alert(result);  
  }
});



/////////////////////////////////////////////////////////////////////////////////
// file: ./ambush/Wall.js
/////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////
// Методы работы со стенами.
// 

Ambush.Wall = Class.create({
	wallPointViewer: null,
	wallUserPoiVisible: [],
	polylines: [],
	visibleBound: null,
	curEditObj: 0,

	ownerType: "",		// Содержит тип стены.
	ownerID: 0,				// Содекжит ID влательца с стены.
	page: 0,					// Текущая страница стены.
	
	initialize: function( ownerType, ownerID, page )
	{
		this.ownerType = ownerType;
		this.ownerID = ownerID;
		this.page = page;
	},

	/**
	 * Метод обновялет список объектов на стене.
	 */
	refreshWall: function()
	{
		action = new WallActions();
		result = action.reloadMessages(this.ownerType, this.ownerID, this.page);
		jQuery("#wallObjectList").html(result);
	},

	/**
	 * Метод редактирует объект.
	 */
	editObject: function( objectID )
	{
		if(this.curEditObj != 0)
		{
			cancelEditWallObject();
		}

		action = new WallActions();
		result = action.showEditMessageForm(this.ownerType, this.ownerID, objectID);
		jQuery('#wall_obj_'+objectID).html(result);
	},

	updateObject: function (objectID)
	{
		action = new WallActions();

		newText = document.forms['editWallMessage'].wallMessage.value;
		result = action.updateWallObject(this.ownerType,this.ownerID, objectID, newText);

		// Провери на наличие ошибки.
		if(result == '')
		{
			// Перегрузим весь список сообщений ...
			this.refreshWall();
		}
		else
			alert(result);

		return false;
	},

	/**
	 * Метод удаляет сообщение со стены, при этом закачивает аяксом обновленный
	 * список объектов.
	 */
	removeObject: function( objectID, page )
	{
		if(confirm('Вы действительно хотите удалить сообщение?'))
		{
			action = new WallActions();
			result = action.deleteWallObject(this.ownerType,this.ownerID, objectID);
			result = action.reloadMessages(this.ownerType, this.ownerID, page);
			jQuery("#wallObjectList").html(result);
		}
	},

	/**
	 * Метод загружает комментарии с сервера.
	 */
	showComments: function( objectID )
	{
		if(jQuery('#wallObject'+objectID+'Comments').html()=='')
		{
			action = new WallActions();
			result = action.showWallComments(this.ownerType, this.ownerID, objectID);
			jQuery('#wallObject'+objectID+'Comments').html(result);
		}
		else
		{
			jQuery('#wallObject'+objectID+'Comments').html('');
		}
	},
	
	/**
	 * Удаляет комментарий, загружает с сервера новый список комментариев.
	 */
	removeComment: function( objectID, commentID )
	{
		if(confirm('Вы действительно хотите удалить комментарий?'))
		{
			action = new WallActions();
			result = action.deleteWallComment(this.ownerType, this.ownerID, objectID, commentID);

			action = new WallActions();
			result = action.showWallComments(this.ownerType, this.ownerID, objectID);
			jQuery('#wallObject'+objectID+'Comments').html(result);
		}
	},

	/**
	* Метод запрашивает с сервера и отображает форму создания комментария
	*/
	newComment: function(objectID, commentID)
	{
		if(jQuery('#wallObject'+objectID+'Comments').html()=='')
			this.showComments(this.ownerType, this.ownerID, objectID);

		action = new WallActions();
		result = action.showNewCommentForm(this.ownerType, this.ownerID, objectID, commentID);

		jQuery("#newWallObjectCommentForm").remove();
		jQuery("#wallObject"+objectID+"Comments").prepend('<div id="newWallObjectCommentForm">'+result+'</div>'); //wallMessageWindow
	},

	/**
	 * Метод загружает с сервера форму для зоздания подкмментариев.
	 */
	newSubComment: function( objectID, commentID)
	{
		action = new WallActions();
		result = action.showNewCommentForm(this.ownerType, this.ownerID, objectID, commentID);

		jQuery("#newWallObjectCommentForm").remove();
		jQuery("#wallComment"+commentID+"Comments").prepend('<div id="newWallObjectCommentForm">'+result+'</div>'); //wallMessageWindow
	},

	/**
	 * Метод сохраняет написанный пользователем комментарий и перегружает аяксом
	 * текст с комментариями.
	 */
	saveComment: function( objectID, commentID)
	{
		action = new WallActions();
		mes = document.forms['newWallComment'].wallComment.value;
		result = action.saveNewWallComment(this.ownerType, this.ownerID, objectID, commentID, mes);

		action = new WallActions();
		result = action.showWallComments(this.ownerType, this.ownerID, objectID);
		jQuery('#wallObject'+objectID+'Comments').html(result);

		return false;
	},

	/**
	* Метод закрывает форму редактора комментария.
	*/
	cancelComment: function(object)
	{
		jQuery("#newWallObjectCommentForm").remove();
	},

	/**
	 * Метод осуществяет переход на другую станицу.
	 */
	gotoPage: function(page)
	{
		// Заменим страницу
		this.page = page;
		// и обновим её ...
		this.refreshWall();

		wallObjectLoad();
	},

	/**
	 * Отображает на карте метру пользователя прекрепленную к стене.
	 */
	showUserPOI: function(ownerType, ownerID, objectID)
	{
		if(map!=null)
		{
			if(this.wallPointViewer==null)
			{
				this.wallPointViewer = new Ambush.UsersPOIViewer(map);
			}

			if(this.wallUserPoiVisible[objectID]==null)
			{
				action = new WallActions();
				point = action.getWallUserPOI(ownerType, ownerID, objectID);

				this.wallUserPoiVisible[objectID]=point.id;
				this.wallPointViewer.addPoint(point);
				mapWindow.normalised();
				this.wallPointViewer.show();

				map.setZoom(14);
				map.panTo(new GLatLng(point.latitude, point.longitude));
			}
			else
			{
				this.wallPointViewer.removePoint(this.wallUserPoiVisible[objectID]);
				this.wallUserPoiVisible[objectID] =null;
			}
		}
		else
		{
			jQuery('#wallUserPOI'+objectID).removeAttr('checked');
			alert('Дождитесь загрузки карты');
		}
	},

	/**
	 * Метод отрисовывает на карте трек присоедененный к стене.
	 */
	showTrack: function (ownerType, ownerId, id, color)
	{
		if(this.polylines["i"+id]==null)
		{
			var thisObj = this;
			action = new WallActions(
			{
				getWallTrack:function(curTrack)
				{
					thisObj.polylines["i"+id] = new GPolyline.fromEncoded({
						color: color,
						weight: 3,
						opacity: 1,
						points: curTrack[0],
						levels: curTrack[1],
						zoomFactor: 32,
						numLevels: 4
					});
					trackLenght = thisObj.polylines["i"+id].getLength();
					map.addOverlay(thisObj.polylines["i"+id]);
					jQuery('#wallTrack'+id+'Load').css('display', 'none');

					thisObj.addMapBound(id);
				}
			});
			jQuery('#wallTrack'+id+'Load').css('display', 'inline');
			action.getWallTrack(ownerType, ownerId, id);

			if(mapWindow._minimised)
			{
				mapWindow.normalised();
			}
		}
		else
		{
			if(mapWindow._minimised)
			{
				mapWindow.normalised();
			}
			this.polylines["i"+id].show();
		}
	},
	/**
	 * Хрен знает что делает...
	 */
	addMapBound: function(lineID)
	{
		if(this.polylines["i"+lineID]!=null)
		{
			if(this.visibleBound!=null)
			{
				this.visibleBound=map.getBounds();
				newBound=this.polylines["i"+lineID].getBounds();
				this.visibleBound.extend(newBound.getSouthWest());
				this.visibleBound.extend(newBound.getNorthEast());
				cntr=this.visibleBound.getCenter();
				zoom=map.getBoundsZoomLevel(this.visibleBound);
				map.setCenter(cntr,zoom);
			}
			else
			{
				this.visibleBound=this.polylines["i"+lineID].getBounds();
				//alert(this.visibleBound.getCenter());
				cntr=this.visibleBound.getCenter()
				zoom=map.getBoundsZoomLevel(this.visibleBound);
				map.setCenter(cntr,zoom);
			}
		}
	},

	/**
	 * Загружает с сервера формы для добавления объектов на стену.
	 */
	addObject: function( objType, owner, ownerID)
	{
		action = new WallActions();
		switch(objType)
		{
			case 'message':
				wallMessageWindow = new Ambush.MapWindow("wallMessageWindow");
				wallMessageWindow.setCaption("Новое сообщение");
				wallMessageWindow.enabledButton("minised");
				wallMessageWindow.enabledButton("close");
				wallMessageWindow.setPrototype($("windowPrototype"));
				wallWindow.addWindow(wallMessageWindow);

				wallMessageWindow.ajaxLoaderOn();
				result = action.showNewMessageForm(owner, ownerID);
				wallMessageWindow.setHTML(result);
				wallMessageWindow.ajaxLoaderOff();
				break;
			case 'poi':
				wallMessageWindow = new Ambush.MapWindow("wallMessageWindow");
				wallMessageWindow.setCaption("Новая метка");
				wallMessageWindow.enabledButton("minised");
				wallMessageWindow.enabledButton("close");
				wallMessageWindow.setPrototype($("windowPrototype"));
				wallWindow.addWindow(wallMessageWindow);

				wallMessageWindow.ajaxLoaderOn();
				result = action.showNewPOIForm(owner, ownerID);
				wallMessageWindow.setHTML(result);
				wallMessageWindow.ajaxLoaderOff();
				break;
			case 'track':
				wallMessageWindow = new Ambush.MapWindow("wallMessageWindow");
				wallMessageWindow.setCaption("Новый трек");
				wallMessageWindow.enabledButton("minised");
				wallMessageWindow.enabledButton("close");
				wallMessageWindow.setPrototype($("windowPrototype"));
				wallWindow.addWindow(wallMessageWindow);

				wallMessageWindow.ajaxLoaderOn();
				result = action.showNewTrackForm(owner, ownerID);
				wallMessageWindow.setHTML(result);
				wallMessageWindow.ajaxLoaderOff();
				break;
		}
	},

	/**
	 * Сохраняет новый объект стены на сервере.
	 */
	saveObject: function(formElement, objectType, owner, ownerID)
	{
		var window = Ambush.getMapWindow(formElement);
		window.ajaxLoaderOn();

		action = new WallActions();
		switch(objectType)
		{
			case 'message':
				//alert(objectType);
				mes=document.forms['newWallMessage'].wallMessage.value;
				//alert(mes);
				result = action.saveNewWallMessage(owner,ownerID,mes);
				//alert(result);
				jQuery("#newWallObjectForm").hide();
				jQuery("#newWallObjectForm").html("");
				result = action.reloadMessages(owner,ownerID);
				//alert(result);
				jQuery("#wallObjectList").html(result);
				break
			case 'poi':
				//alert(objectType);
				mes=document.forms['newWallPOI'].wallPOIMessage.value;

				var radioGrp = document.forms['newWallPOI'].wallPOI;
				if(radioGrp!=null && radioGrp.length!=undefined)
				{
					for (var i = 0; i< radioGrp.length; i++) {
						if (radioGrp[i].checked) {
							poiID=radioGrp[i].value;//document.forms['newWallPOI'].wallPOI.value;
							//alert("The value of the chosen button is " + radioGrp[i].value);
						}
					}
				}
				else
				{
					if(radioGrp!=null)
					{
						poiID=radioGrp.value
					}
					else
					{
						alert("точка не выбрана");
					}
				}

				//alert(poiID);
				result = action.saveNewWallPOI(owner,ownerID,mes,poiID);
				//alert(result);
				jQuery("#newWallPOIForm").hide();
				jQuery("#newWallPOIForm").html("");
				result = action.reloadMessages(owner,ownerID);
				//alert(result);
				jQuery("#wallObjectList").html(result);
				break;
			case 'track':
				//alert(objectType);
				mes=document.forms['newWallTrack'].wallTrackMessage.value;

				var radioGrp = document.forms['newWallTrack'].wallTrack;
				if(radioGrp!=null && radioGrp.length!=undefined)
				{
					for (var i = 0; i< radioGrp.length; i++) {
						if (radioGrp[i].checked) {
							trackID=radioGrp[i].value;//document.forms['newWallPOI'].wallPOI.value;
							//alert("The value of the chosen button is " + radioGrp[i].value);
						}
					}
				}
				else
				{
					if(radioGrp!=null)
					{
						trackID=radioGrp.value
					}
					else
					{
						alert("трек не выбран");
					}
				}

				//alert(poiID);
				result = action.saveNewWallTrack(owner,ownerID,mes,trackID);
				//alert(result);
				jQuery("#newWallTrackForm").hide();
				jQuery("#newWallTrackForm").html("");
				result = action.reloadMessages(owner,ownerID);
				//alert(result);
				jQuery("#wallObjectList").html(result);
				break;
			default:
				break
		}
		window.close(true);
		return false;
	}
});

/**
 * Реализация общей стены, требует переобределения 
 */
Ambush.CommonWall = Class.create(Ambush.Wall, {

	showComments: function( objectID )
	{
		jQuery('#wallObject'+objectID+'Comments').toggle();
	},


	removeObject: function( objectID, page )
	{
		if(confirm('Вы действительно хотите удалить сообщение?'))
		{
			action = new WallActions();
			result = action.deleteWallObject( this.ownerType, this.ownerID, objectID);
			result = action.getCommonWallObjects(this.ownerType, this.ownerID, page);
			jQuery("#wallObjectList").html(result);
		}
	},

	newComment: function( objectID, commentID )
	{
		action = new WallActions();
		jQuery('#wallObject'+objectID+'Comments').show();
		result = action.showNewCommentForm( this.ownerType, this.ownerID, objectID, commentID);

		jQuery("#newWallObjectCommentForm").remove();
		jQuery("#wallObject"+objectID+"Comments").prepend('<div id="newWallObjectCommentForm">'+result+'</div>');
	},

	/**
	 * Отображает POI на общей стене.
	 */
	showUserPOI: function(ownerType, ownerID, objectID)
	{
		if(map!=null)
		{
			if(this.wallPointViewer == null)
			{
				this.wallPointViewer = new Ambush.UsersPOIViewer(map);
			}

			if(this.wallUserPoiVisible[objectID]==null)
			{
				action = new WallActions();
				point = action.getWallUserPOI(ownerType, ownerID, objectID);

				this.wallUserPoiVisible[objectID]=point.id;
				this.wallPointViewer.addPoint(point);
				this.wallPointViewer.show();

				map.setZoom(14);
				map.panTo(new GLatLng(point.latitude, point.longitude));
			}
			else
			{
				this.wallPointViewer.removePoint(this.wallUserPoiVisible[objectID]);
				this.wallUserPoiVisible[objectID] = null;
			}
		}
		else
		{
			jQuery('#wallUserPOI'+objectID).removeAttr('checked');
			alert('Дождитесь загрузки карты');
		}
	},

	/**
	 * Переопределим отображатель треков, так как в данной реализации не требуется
	 * использование окон (MapWindow)
	 */
	showTrack: function(ownerType, ownerId, id, color)
	{
		if(this.polylines["i"+id]==null)
		{
			var thisObj = this;
			action = new WallActions(
			{
				getWallTrack:function(curTrack)
				{
					thisObj.polylines["i"+id] = new GPolyline.fromEncoded({
						color: color,
						weight: 3,
						opacity: 1,
						points: curTrack[0],
						levels: curTrack[1],
						zoomFactor: 32,
						numLevels: 4
					});
					trackLenght=thisObj.polylines["i"+id].getLength();
					map.addOverlay(thisObj.polylines["i"+id]);
					jQuery('#wallTrack'+id+'Load').css('display', 'none');
					thisObj.addMapBound(id);
				}
			});

			jQuery('#wallTrack'+id+'Load').css('display', 'inline');
			action.getWallTrack(ownerType, ownerId, id);
		}
		else
		{
			this.polylines["i"+id].show();
		}
	}
});



/////////////////////////////////////////////////////////////////////////////////
// file: ./ambush/ambush.js
/////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
//
//

