var AWP = {
	cfg: null,
	map: null,

	/**
	 * AWP Component
	 */
	mainPanel: null,
	tabPanel: null,

	/**
	 * The entrance of AWP.
	 */
	init: function() {
		AWP.cfg = new AWP.Configuration();

		Ext.QuickTips.init();
		Ext.BLANK_IMAGE_URL = AWP.cfg.AWP_URL + 'image/s.gif';
		//Ext.state.Manager.setProvider(new Ext.state.CookieProvider());

		var mainPanel = AWP.Control.Layout.AWP();
		var tabPanel = AWP.Layer.TabPanel.AWP();

		var southPanel = mainPanel.getComponent('south');
		var height = southPanel.getInnerHeight() - document.getElementById('tab_title').offsetHeight - 2;
		tabPanel.setHeight(height);

		var tree = new AWP.Layer.Tree({renderTo: 'layer-tree1', category: ['PFRA', 'topcanada_wms']});
		var tree2 = new AWP.Layer.Tree({renderTo: 'layer-tree2', category: ['bg_layers']});

		var map = new AWP.Map('map');
		map.init();
		map.events.register("zoomend", tree, tree.updateNodes);
		var control = map.getControlsByClass('AWP.Control.SelectFeature')[0];
		if (control) control.activate();

		tree.updateNode(tree.root, map.getScale());

		AWP.mainPanel = mainPanel;
		AWP.tabPanel = tabPanel;
		AWP.map = map;

		var h_space = 5;
		var tb_main = document.getElementById('map-main');
		var h_tbar = document.getElementById('map-tbar').offsetHeight + h_space;
		var h_bbar = document.getElementById('map-bbar').offsetHeight + h_space + h_space;
		var h_main = tb_main.offsetHeight - h_tbar - h_bbar;
		//alert([h_tbar,h_main,h_bbar])
		tb_main.rows[0].style.height = h_tbar + 'px';
		tb_main.rows[1].style.height = h_main + 'px';
		tb_main.rows[2].style.height = h_bbar + 'px';

		var h_wrap = h_main;
		var map_wrap = document.getElementById('map-wrap');
		map_wrap.style.height = h_wrap + 'px';
		map_wrap.rows[1].style.height = h_wrap - 18 + 'px';
		document.getElementById('map').style.height = h_wrap - 18 + 'px';
		AWP.map.updateSize();
		// 2009-07-03, Ma: since the "south" panel be expanded all the time, below events are no longer needed
		//mainPanel.addListener('afterlayout', map.updateSize, map);
		//mainPanel.getComponent('south').addListener('expand', tabPanel.expandHeight, tabPanel);
	},
	/**
	 * AWP 项目后台编辑 Water Data 时调用
	 */
	initAWPAdmin: function(x, y) {
		AWP.cfg = new AWP.Configuration();
		
		if (Ext) {
			Ext.QuickTips.init();
			Ext.BLANK_IMAGE_URL = AWP.cfg.baseURL + 'image/s.gif';
		}
		
		// 切换 Google Map 时用到了 AWP.map
		var map = AWP.map = new AWP.Map('map');
		map.initAWPAdmin(x, y);
		
		var tree2 = new AWP.Layer.Tree({renderTo: 'layer-tree2', initAWPAdmin: true, category: ['bg_layers']});
	},
	/**
	 * The entrance of SEAWA.
	 */
	initSEAWA: function() {
		AWP.cfg = new AWP.Configuration();
		
		Ext.QuickTips.init();
		Ext.BLANK_IMAGE_URL = AWP.cfg.AWP_URL + 'image/s.gif';
		//Ext.state.Manager.setProvider(new Ext.state.CookieProvider());
		
		
		/**
		 * 主面板布局后，左中右的宽度可随之确定，地图的宽度也确定下来
		 */
		var mainPanel = AWP.mainPanel = AWP.Control.Layout.SEAWA();
		//var tabPanel = AWP.tabPanel = AWP.Layer.TabPanel.SEAWA();
		//var westPanel = mainPanel.getComponent('west');
		//var eastPanel = mainPanel.getComponent('east');
		//westPanel.addListener('expand', tabPanel.adjustWidth, tabPanel);
		//westPanel.addListener('collapse', tabPanel.adjustWidth, tabPanel);
		//eastPanel.addListener('expand', tabPanel.adjustWidth, tabPanel);
		//eastPanel.addListener('collapse', tabPanel.adjustWidth, tabPanel);


		/**
		 * 初始化地图前确定地图的大小，可以避免再次调用地图的 updateSize() 方法
		 */
		var map_wrap = document.getElementById('map-wrap2');
		var w_map = map_wrap.offsetWidth;
		var h_map = Math.round(w_map * AWP.cfg.LAYOUT.seawaRatio);	// 宽 x 宽高比 = 高
		map_wrap.style.height = h_map + 'px';

		var map = AWP.map = new AWP.Map('map');
		map.initSEAWA();

		// 地图高度确定，随即设置包含地图的 tr 的高度，上下圆角各9px高，已经写在模板中
		// 似乎 firefox 不需要以下设置
//		var map_tbwrap = document.getElementById('map-wrap');
//		map_tbwrap.rows[1].style.height = h_map + 'px';

		var h_space = 5;
		var h_tbar	= document.getElementById('map-tbar').offsetHeight + h_space;
		var h_main	= h_map + 18;	// 上下圆角共18px
		var h_bbar	= document.getElementById('map-bbar').offsetHeight + h_space + h_space;

		// 似乎 firefox 不需要以下设置
//		var tb_main = document.getElementById('map-main');
//		tb_main.rows[0].style.height = h_tbar + 'px';
//		tb_main.rows[1].style.height = h_main + 'px';
//		tb_main.rows[2].style.height = h_bbar + 'px';

		// 根据地图（包括顶部工具栏，地图及圆角，底部工具栏）实际高度，调整 mainPanel 的高度
		mainPanel.setHeight(h_tbar + h_main + h_bbar + 15);


		/**
		 * 载入图层树
		 */
		var tree  = new AWP.Layer.Tree({renderTo: 'layer-tree1', category: AWP.Configuration.prototype.tree1Categories});
		var tree2 = new AWP.Layer.Tree({renderTo: 'layer-tree2', category: ['bg_layers']});
		var tree3 = new AWP.Layer.Tree({renderTo: 'layer-tree3', model: AWP.cfg.CATEGORIES[AWP.Configuration.tree3Category].children});
		tree3.gidInfo = {};
		// 左上角 Indicators 树
		var treeModel	= {
			category	: AWP.cfg.SEAWA,
			checked		: false,
			basin_name	: false,	// 用于 显示/隐藏所有的 indicators
			text		: 'Show/Hide All',
			expanded	: true,
			children	: []
		};
		for (var i = 0, basin; basin = AWP.Configuration.prototype.SEAWA_BASINS[i]; i++) {
			treeModel.children.push({
				category	: AWP.cfg.SEAWA,
				checked		: false,
				gid			: basin.gid,
				basin_name	: basin.basin_name,	// 用于 显示/隐藏 sub basin 的 indicators
				text		: basin.basin_name,
				tbname		: basin.tbname
			});
		}
		var tree4 = new AWP.Layer.Tree({renderTo: 'layer-tree4', model: [treeModel]});
		tree4.gidInfo = tree3.gidInfo;
		tree.updateNode(tree.root, map.getScale());
		map.events.register("zoomend", tree, tree.updateNodes);
		map.getControlsByClass('AWP.Control.SelectFeature')[0].activate();
		
		
		/**
		 * 载入用户数据分类树，显示实时数据指示层
		 * 1. 用户数据分类树的节点的点击事件在 TreeNode.js 文件 renderElements 方法中决定
		 * <a href="javascript:void(0)" class="user-feature" ...
		 * @date 2010-08-19 #82 需求：去掉左侧 Member Contents 选项
		 */
		//AWP.userContent.displayContentTree();
		/**
		 * 根据后台设置显示已定义 icon 的实时数据的 indicator 层
		 * @date 2010-08-19 #82 需求：去掉右侧 Real-time Data 选项，那么此处 动态求得子图层 也就不需要了
		 */
		//AWP.Layer.Markers.showRealtimeIndicatorLayers(tree);


		/**
		 * 2009-10-19
		 *   Change Google Earth to a popup window.
		 * 2010-03-04
		 * 	 Trigger it by externel button.
		 */
		if (typeof AWP.Control.GoogleEarth != 'undefined') {
		map.googleEarth = new AWP.Control.GoogleEarth();
		map.addControl(map.googleEarth);
		//map.googleEarth.activate();
		}
	},
	initSEAWAUserContent: function() {
		AWP.cfg = new AWP.Configuration();

		Ext.QuickTips.init();
		Ext.BLANK_IMAGE_URL = AWP.cfg.AWP_URL + 'image/s.gif';
		
		/**
		 * 初始化地图前确定地图的大小，可以避免再次调用地图的 updateSize() 方法
		 */
		var map_wrap = document.getElementById('map-wrap2');
		var w_map = map_wrap.offsetWidth;
		var h_map = Math.round(w_map * AWP.cfg.LAYOUT.seawaRatio);	// 宽 x 宽高比 = 高
		map_wrap.style.height = h_map + 'px';
		
		var map = AWP.map = new AWP.Map('map');
		map.initSEAWA();
		
		/**
		 * 载入用户数据分类树，显示实时数据指示层
		 * 1. 用户数据分类树的节点的点击事件在 TreeNode.js 文件 renderElements 方法中决定
		 * <a href="javascript:void(0)" class="user-feature" ...
		 */
		AWP.userContent.displayContentList('customer_content_list2');
		AWP.user.showPopupContent = function() {}
		
		/**
		 * 劫持 Ext.Ajax.request。先判断用户 session 是否已过期，过期则跳转，否则继续正常请求
		 
		AWP.ext_ajax_request = Ext.Ajax.request;
		Ext.Ajax.request = function(o) {
			AWP.ext_ajax_request.call(Ext.Ajax, {
				url: AWP.cfg.serviceURL,
				params: {
					action: 'checkLoginStatus'
				},
				success: function(response, options) {
					var is_no_login = response.responseText.indexOf('<input type="hidden" name="task" value="login" />');
					if (is_no_login != -1) {
						window.location.reload();
					} else {
						AWP.ext_ajax_request.call(Ext.Ajax, o);
					}
				}
			});
		}*/

		AWP.openlayers_request_issue = OpenLayers.Request.issue;

		OpenLayers.Request.issue = function(config) {
			new Ajax(AWP.cfg.serviceURL, {
				method : 'get',
				onSuccess : function (responseText) {
					var is_no_login = responseText.indexOf('<input type="hidden" name="task" value="login" />');
					if (is_no_login != -1) {
						window.location.reload();
					} else {
						AWP.openlayers_request_issue.call(OpenLayers.Request, config);
					}
				}
			}).request();
		}
	},
	/**
	 * The entrance of AWP Water Data Details.
	 */
	initWaterData: function(x, y) {
		AWP.cfg = new AWP.Configuration();
		
		var map = new AWP.Map('map');
		map.iniAWPWatertData(x, y);
		AWP.map = map;
	},
	searchByCircle: function(x, y, r) {
		var controlSearch = this.map.getControlsByClass('AWP.Control.Search')[0];
		var xy = new OpenLayers.LonLat(x, y);
		xy = xy.transform(this.map.proj_4326, this.map.proj_900913);
		var r = typeof r == 'string' ? controlSearch.proximity(r) : controlSearch.proximity();

		var layer = controlSearch.findLayer(), area = 0;
		if (layer.layerId == 'helen_edit') {
			area = controlSearch.areaLimit('area-limitation');
		}
		this.mainPanel.expandSouth(controlSearch.zoomByCircle, controlSearch, [xy, r, area]);
	},
	/**
	 * 根据传入的 region_id，去 $cfg['regions_to_zoom'] 中寻找配置。如果有 layerId，那么在地图上显示此 layer
	 */
	zoomToRegion: function(gid, layerId) {
		var map	= AWP.map,
			ge	= map.googleEarth && map.googleEarth.ge;
		var center, newCenter, oldCenter = map.getCenter();
		var altitude = 0, heading = 0, tilt = 15, range = 400000;
		
		OpenLayers.Request.GET({
			url		: AWP.cfg.serviceURL + '&action=getRegionGeometry&gid=' + gid + '&tbname=' + layerId,
			success	: function(response) {
				var feature = new OpenLayers.Format.WKT().read(response.responseText);
				if (feature) {
					var bounds		= feature.geometry.getBounds();
					var zoomLevel	= map.getZoomForExtent(bounds) + 1;
					var lonlat		= bounds.getCenterLonLat();
					map.setCenter(lonlat, zoomLevel);
				} else {
					alert('No feature(s) found');
				}
				return
				/**
				 * 调试 basin 几何图形的代码
				var layer = AWP.map.getLayerByName("test");
				if (!layer) {
					layer = new AWP.Layer.Vector({name: "test"});
					AWP.map.addLayer(layer);
				}
				
				layer.destroyFeatures(layer.features);
				layer.features = [];
				layer.addFeatures([feature]);
				layer.setVisibility(true);
				*/
				
				if (ge) {
					try {
						google.earth.removeEventListener(ge, "frameend", map.googleEarth.onFrameEnd);
					} catch(e) {
						//alert(e);
					}
					map.googleEarth.look(bounds);
				}
			},
			failure	: function() {alert('Can not find region : ' + region_id)},
			scope	: this
		});
	},

	/**
	* 模拟点击动作 显示盆地的轮廓，或者子盆地模块
	*
	* @type		boolean		true 显示所有子盆地 false 显示所有子盆地 + 轮廓
	*/
	showTheBasin : function(type)
	{
		type = type || true;

		var chks = $('layer-tree3').getElements('input[type=checkbox]');
		var len  = chks.length;

		if (type)
		{
			chks[len-1].checked = false;
			chks[len-1].click();
		}
		else
		{
			chks.each(function(chk)
			{
				chk.checked = false;
				chk.click();
			});
		}
	},

	/**
	* 跳转到具体的盆地块
	*/
	zoomToSubBasin: function(basinId, tbl) {
		/**
		 * @date 2010-06-02 malian
		 * 没发现这行有什么用。
		 */
		//this.showTheBasin();
		
		/**
		 * 隐藏所有其他非背景层
		 */
		var layerId = AWP.cfg.SEAWA_GE_DEFAULT_LAYER_ID;
		if (layerId && AWP.Layer.items[layerId]) {
			for (var i in AWP.Layer.items) {
				var layer = AWP.Layer.items[i];
				if (i != layerId && !layer.isBaseLayer && layer.getVisibility()) {
					layer.setVisibility(false);
				}
			}
		}
		
		var map = AWP.map, ge = map.googleEarth && map.googleEarth.ge;
		var center, newCenter, oldCenter = map.getCenter();
		var altitude = 0, heading = 0, tilt = 15, range = 400000;

		basinId = basinId || 0;
		tbl		= tbl || 'seawa_sub_prj';

		if (basinId == 0) {
			return false;
		}
		
		OpenLayers.Request.GET({
			url: AWP.cfg.serviceURL + '&action=ajaxSubBasin&tbl=' + tbl + '&basinId=' + basinId,
			success: function(response) {
				var feature		= new OpenLayers.Format.WKT().read(response.responseText);
				var bounds		= feature.geometry.getBounds();
				var zoomLevel	= map.getZoomForExtent(bounds);
				var lonlat		= bounds.getCenterLonLat();
				map.setCenter(lonlat, zoomLevel);
				
				/**
				 * 显示当前 region 关联的层
				 */
				if (layerId && AWP.Layer.items[layerId]) {
					AWP.Layer.items[layerId].setVisibility(true);
					if (layerId == AWP.cfg.SEAWA_GE_DEFAULT_LAYER_ID) {
						AWP.Layer.items[AWP.cfg.SEAWA_GE_DEFAULT_LAYER_ID + '_icon'].setVisibility(true);
					}
				}
				
				if (ge) {
					try {
						google.earth.removeEventListener(ge, "frameend", map.googleEarth.onFrameEnd);
					} catch(e) {
						alert(e);
					}
					
					map.googleEarth.look(bounds);
				}
			},
			failure: function() {
				alert('Can not find region : ' + basinId)
			},
			scope: this
		});
	},
	/**
	 * 点击 "Sub-Basins" 按钮后出现选择列表
	 */
	downList: function(ListId, height) {
		height = height + 20;
		
		var myFlow = $(ListId);
		document.body.insertBefore(myFlow, null);
		myFlow.setStyles({'display': ''});
		
		var jason_timer  = null;
		
		/**
		 * 给 table 设置 widht:auto 使得在 IE7 下其宽度不占100%
		 */
		var cs = myFlow.childNodes, tb;
		for (var i = 0, len = cs.length; i < len; i++) {
			if (cs[i].tagName == 'TABLE') {
				tb = cs[i];
				break;
			}
		}
		if (tb) {
			tb.style.width = 'auto';
		}

		var fx = new Fx.Style(myFlow, 'height', {duration: 500});

		lists = myFlow.getElements('li');
		lists.each(function(item) {
			item.addEvent('mouseover', function() {
				this.className = 'item hover';
			});
			item.addEvent('mouseout', function() {
				this.className = 'item';
			});
		});
		
		var down_fun = function() {
			var btn	= $('btn_sub_basins');
			
			this.element.style.position = 'absolute';
			var pos	= (function(forElement) {
			    var valueT = 0, valueL = 0;
			
			    var element = forElement;
			    var child = forElement;
			    while(element) {
			
			        if(element == document.body) {
			            if(OpenLayers.Element.getStyle(child, 'position') == 'absolute') {
			                break;
			            }
			        }
			        
			        valueT += element.offsetTop  || 0;
			        valueL += element.offsetLeft || 0;
			
			        child = element;
			        try {
			            element = element.offsetParent;
			        } catch(e) {
			            break;
			        }
			    }
			    return [valueL, valueT];
			})(btn);
			top		= pos[1] + btn.offsetHeight - 5;
			left	= pos[0];
			this.element.style.top = top + 'px';
			this.element.style.left = left + 'px';
			this.element.style.zIndex = 9999;
		}

		if (myFlow.className == 'close') {
			down_fun.call(fx);
			//jason_timer = window.setInterval(down_fun.bind(fx), 5000);
			fx.start(0, height);
			myFlow.className = 'open';
		} else {
			//$clear(jason_timer);
			fx.start(height, 0);
			myFlow.className = 'close';
		}
	},
	// 此方法似乎已没有地方再使用，暂时保留其中代码供参考
	getKMLByName: function(name, category) {
		Ext.Ajax.request({
			url: AWP.cfg.serviceURL,
			params: {
				action: 'AWP.getKMLByName',
				name: name,
				category: category,
				user_id: AWP.user ? AWP.user.id : 0,
				format: 'json'
			},
			success: function(response, options) {
				try {
					var json = eval('(' + response.responseText + ')');
				} catch (e) {
					alert(e + '\n\n' + response.responseText);
				}

				var format = new AWP.Format.KML({extractStyles: true});
				var features = [], rows = json.rows;

				var names = {};
				for (var i in rows) {
					var row = rows[i];
					names[row.name] = names[row.name] ? names[row.name] + 1 : 1;

					if (row.kml) {
						var feature = format.read(row.kml)[0];
						if (feature) {
							var style = null;
							for (var styleName in format.styles) {
								if (format.styles[styleName]) {
									style = format.styles[styleName];
									break;
								}
							}
							if (style != null) {
								feature.style = OpenLayers.Util.extend(
									OpenLayers.Util.extend(
										{},
										OpenLayers.Feature.Vector.style['default']
									), style);
							}

							feature.fid = row.gid;
							for (var key in row) {
								if (key == 'kml' || key == 'gid') continue;
								feature.attributes[key] = row[key];
							}
							features.push(feature);
						}
					}
				}

				AWP.map.getLayerByName('Editable').addFeatures(features);
			},
			failure: function() {alert('sorry')},
			callback: function(options, status, response) {}
		});
	},
	log: function(json) {
		if (arguments.length == 2) {
			var a = {debug: {}};
			a.debug[arguments[0]] = arguments[1];
			var json = a;
		}
		if (json.debug) {
			var debug = json.debug || {};
			var info = Ext.get('map_info');
			//info.fadeIn({ endOpacity: .75, duration: 1});

			var dt = new Date(), div = document.createElement('div');
			var html = ['<table width="100%" border="1" cellpadding="3" cellspacing="0">'];
			for (var key in debug) {
				html = html.concat([
					'  <tr>',
					'    <td width="60" align="left">' + dt.format('H:i:s') + '</td>',
					'    <td width="40" align="left">' + dt.getMilliseconds() / 1000 + '</td>',
					'    <td align="left">' + key + ': ' + debug[key] + '</td>',
					'  </tr>'
				]);
			}
			html.push('</table>');
			div.innerHTML = html.join('\n');
			info.appendChild(div);
		}
	},
	info: function() {
		var map = AWP.map;

		var s = [];
		for (var i = 0, len = map.layers.length; i < len; i++) {
			var layer = map.layers[i];
			s.push(layer.name + ',' + layer.getZIndex());
		}
		alert(s.join('\n'));
		return

		var info = '';
		info += 'getNumZoomLevels(): ' + map.getNumZoomLevels() + '<br />';
		info += 'getZoom(): ' + map.getZoom() + '<br />';

		info += 'resolutions: ' + map.resolutions + '<br />';
		info += 'getMaxResolution(): ' + map.getMaxResolution() + '<br />';
		info += 'getResolution(): ' + map.getResolution() + '<br />';
		info += 'getResolutionForZoom(): ' + map.getResolutionForZoom() + '<br />';
		info += 'getZoomForResolution(): ' + map.getZoomForResolution() + '<br />';
		info += 'getMaxExtent(): ' + map.getMaxExtent() + '<br />';
		document.getElementById('info').innerHTML = info;
	},
	preEvent: function() {
		var out = [], o = OpenLayers.Event.observers;

		for (var cache_id in o) {
			var obj = [cache_id], a = o[cache_id];
			for (var i = 0, len = a.length; i < len; i++) {
				var b = a[i];
				//s.push('\telement: <' + b.element.tagName + ' id=' + b.element.id);
				obj.push(b.name);
				//s.push('\tfunc: ' + b.observer)
			}
			out.push(obj);
		}
		pre(out.slice(-5));
	},
	preEvents: function(events) {
		if (!events) {
			pre(OpenLayers.Events.array.slice(-5));
			return;
		}
		var o = {}, el = events.element, ls = events.listeners;
		o.object = events.object.CLASS_NAME;
		if (el) {
			o.element = '<' + el.tagName + ' id=' + el.id + '>' + el.innerHTML;
			o.cache_id = el._eventCacheID;
		}
		o.includeXY = events.includeXY;
		o.eventTypes = events.eventTypes;
		o.listeners = {};
		for (var type in ls) {
			o.listeners[type] = [];
			for (var i = 0, len = ls[type].length; i < len; i++) {
				var l = ls[type][i];
				o.listeners[type].obj = l.obj.CLASS_NAME;
				o.listeners[type].func = typeof l.func;
			}
		}
		pre(o);
	},
	t: false,
	pre: function(a) {
		var op = document.getElementById('map_info');
		op.innerHTML += a + '<br />';
		if (!AWP.t) {
			//new OpenLayers.Events

			AWP.t = true;
		}
	},
	createRecords: function(rows) {
		var fields	= rows.shift();
		var num		= fields.length;
		var len		= rows.length;
		var key		= '';
		
		for (var j = 0; j < num; j++) {
			if (fields[j] == 'id') key = 'id';
		}
		
		var records = key == 'id' ? {} : [];
		for (var i = 0; i < len; i++) {
			var row = rows[i], record = {};
			for (var j = 0; j < num; j++) {
				record[fields[j]] = row[j];
			}
			records[key == 'id' ? record[key] : i] = record;
		}
		
		return records;
	}
};

function update_camera_and_lookat() {
	if (AWP.map.googleEarth) {
		var ge = AWP.map.googleEarth.ge;
		var lookAt = ge.getView().copyAsLookAt(ge.ALTITUDE_RELATIVE_TO_GROUND);
		document.getElementById("id_zl_la").innerHTML = AWP.map.getZoom();
		document.getElementById("id_lat_la").innerHTML = lookAt.getLatitude().toFixed(5);
		document.getElementById("id_lng_la").innerHTML = lookAt.getLongitude().toFixed(5);
		document.getElementById("id_rng_la").innerHTML = lookAt.getRange().toFixed(2);
		document.getElementById("id_alt_la").innerHTML = lookAt.getAltitude().toFixed(2);
		document.getElementById("id_head_la").innerHTML = lookAt.getHeading().toFixed(2);
		document.getElementById("id_tilt_la").innerHTML = lookAt.getTilt().toFixed(2);
	}
}

