AWP.Layer = OpenLayers.Class(OpenLayers.Layer.WMS, {
	layerId: '',
	title: 'Untitled Layer',
	category: '',
	/**
	 * For tree
	 */
	text: '',
	icon: '',
	checked: false,
	position: null,
	
	layers: '',
	maxScale: null,
 	server: null,
	namespace: '',
	
	awp_tab: null,
	awp_store: null,
	awp_grid: null,
	awp_columns: null,
	awp_wkt: new OpenLayers.Format.WKT(),
	
	awp_tab2: null,
	awp_store2: null,
	awp_grid2: null,
	
    initialize: function(config) {
		config = config || {};
		
		this.layerId = config.layerId || '';
		this.category = config.category || '';
		this.minScale = config.minScale || null;
		this.maxScale = config.maxScale || null;
		this.server = config.server || {};
		this.checked = config.checked === true ? true : false;
		/**
		 * only layers is enough to identify a layer
		 */
		this.namespace = config.namespace || this.server.namespace;
		this.layers = (this.namespace ? this.namespace + ':' : '') + (config.layers || '');
		
		this.text = config.name || this.layerId || 'Untitled layer';
		this.icon = config.icon || 'image/layer.png';
		
		var url = this.server.url || AWP.cfg.WMS_URL;
		
		var params = {
			layers: this.layers,
			format: config.format || 'image/png',
			transparent: config.transparent === false ? false : true
		}
		var options = {
			opacity: config.opacity || 1,
			visibility: config.checked === true ? true : false,
			minScale: this.minScale || this.server.minScale || null,
			maxScale: this.maxScale || this.server.maxScale || null
		}
		
		OpenLayers.Layer.WMS.prototype.initialize.apply(this, [this.text, url, params, options]);
		
		if (config.styles) this.children = config.styles;
		if (config.columns) this.awp_columns = config.columns;
		if (config.listable) this.listable = true;
		if (config.isBaseLayer) this.isBaseLayer = true;
		
		AWP.Layer.array.push(this);
		AWP.Layer.items[this.layerId] = this;
    },
	findByKeywords: function(keywords) {
		if (!this.awp_tab) {
			var callback = OpenLayers.Function.bind(function() {
				this.fetchDataByKeywords(keywords);
			}, this);
			this.initTabGridByKeywords(callback);
		} else {
			this.awp_tab.show();
			this.fetchDataByKeywords(keywords);
		}
	},
	findByProximity: function(xy, r, area) {
		if (!this.awp_tab) {
			var callback = OpenLayers.Function.bind(function() {
				this.fetchDataByProximity(xy, r, area);
			}, this);
			this.initTabGridByProximity(callback);
		} else {
			this.awp_tab.show();
			this.fetchDataByProximity(xy, r, area);
		}
	},
	findByFeature: function(layers, gid, area) {
		if (!this.awp_tab) {
			var callback = OpenLayers.Function.bind(function() {
				this.fetchDataByFeature(layers, gid, area);
			}, this);
			this.initTabGridByKeywords(callback);
		} else {
			this.awp_tab.show();
			this.fetchDataByFeature(layers, gid, area);
		}
	},
	initTabGridByKeywords: function(callback) {
		OpenLayers.Request.GET({
			url: AWP.cfg.serviceURL
				+ 'action=getLayerColumnsOfKeywords'
				+ '&layerName=' + this.layers
				+ '&format=json',
			success: function(response) {
				this.initTabGridCallback(response);
				if (callback) callback();
			},
			failure: function() {alert('sorry')},
			scope: this
		});
	},
	initTabGridByProximity: function(callback) {
		OpenLayers.Request.GET({
			url: AWP.cfg.serviceURL
				+ 'action=getLayerColumns'
				+ '&layerName=' + this.layers
				+ '&format=json',
			success: function(response) {
				this.initTabGridCallback(response);
				if (callback) callback();
			},
			failure: function(response) {
				alert('Failed to get grid columns information.'
					//+ '\n\n' + response.responseText
				)
			},
			scope: this
		});
	},
	fetchDataByProximity: function(xy, r, area) {
		this.awp_store.baseParams = {
			action: 'getFeaturesByProximity',
			layerName: this.layers,
			lon: xy.lon,
			lat: xy.lat,
			distance: r,
			area: area,
			resolution: this.map.getResolution(),
			format: 'json'
		};
		
		//this.awp_store.setDefaultSort(sort, dir);
		this.awp_store.load({params: {start: 0}});
	},
	fetchDataByKeywords: function(keywords) {
		this.awp_store.baseParams = {
			action: 'getFeaturesByKeywords',
			layerName: this.layers,
			keywords: keywords,
			resolution: this.map.getResolution(),
			format: 'json'
		};
		
		//this.awp_store.setDefaultSort(sort, dir);
		this.awp_store.load({params: {start: 0}});
	},
	fetchDataByFeature: function(layers, gid, area) {
		this.awp_store.baseParams = {
			action: 'getFeaturesByGeometry',
			layerName: this.layers,
			featureLayerName: layers,
			gid: gid,
			area: area,
			resolution: this.map.getResolution(),
			format: 'json'
		};
		
		//this.awp_store.setDefaultSort(sort, dir);
		this.awp_store.load({params: {start: 0}});
	},
	initTabGridCallback: function(response) {
		try {
			var json = eval('(' + response.responseText + ')');
		} catch (e) {
			alert(e + '\n\n' + response.responseText);
			return
		}
		
		var store_columns = json['store_columns'];
		var grid_columns = json['grid_columns'];
		
		if (!this.awp_tab) {
			var tab_id = 'awp-tabpanel-tab-' + this.layerId;
			var tab = AWP.tabPanel.getItem(tab_id);
			if (!tab) {
				tab = AWP.tabPanel.add({id: tab_id, title: this.name, closable: true});
				tab.show();
				//tab.addListener('activate', this.showTab, this);
				tab.addListener('deactivate', this.hideTab, this);
				tab.addListener('beforedestroy', this.clearFeatures, this);
			}
			this.awp_tab = tab;
		}
		
		if (!this.awp_store) {
			this.awp_store = new AWP.Layer.Store(store_columns);
			this.awp_store.addListener('load', this.afterLoad, this);
			this.awp_store.addListener('beforeload', this.setResolution, this);
		}
		if (!this.awp_grid) {
			var grid_columns_copy = [];
			if (this.awp_columns) {
				if (this.awp_columns['expander']) {
					var expander = new Ext.grid.RowExpander({
						tpl: new Ext.Template(this.awp_columns['expander'].join(''))
					});
					grid_columns_copy.push(expander);
				}
				
				for (var i in this.awp_columns) {
					if (i == 'expander') continue;
					
					var column = grid_columns[i], new_column = this.awp_columns[i];
					if (column && new_column !== false) {
						for (var key in new_column) column[key] = new_column[key];
						grid_columns_copy.push(column);
					}
					if (column) delete grid_columns[i];
				}
			}
			for (var i in grid_columns) {
				grid_columns_copy.push(grid_columns[i]);
			}
			
			this.awp_grid = new AWP.Layer.Grid({
				tab: tab,
				layer: this,
				store: this.awp_store,
				columns: grid_columns_copy,
				plugins: expander || null
			});
			this.awp_grid.render();
			var vectorLayer = this.map.getLayerByName('Vector Features');
			vectorLayer.events.register("featureselected", this, this.selectRowByFeature);
			vectorLayer.events.register("featureunselected", this, this.unselectRowByFeature);
		}
	},
	/*
	showTab: function() {
		var vectorLayer = this.map.getLayerByName("Vector Features");
		if (this.features) {
			vectorLayer.addFeatures(this.features);
			
			var maxBounds = new OpenLayers.Bounds();
			for (var i = 0, len = this.features.length; i < len; i++) {
				maxBounds.extend(this.features[i].geometry.getBounds());
			}
			
			var zoomLevel = this.map.getZoomForExtent(maxBounds);
			this.map.zoomTo(zoomLevel);
		}
	},*/
	hideTab: function() {
		var vectorLayer = this.map.getLayerByName("Vector Features");
		if (this.features) {
			this.map.getControlsByClass('AWP.Control.SelectFeature')[0].unselectAll();
			vectorLayer.removeFeatures(this.features);
		}
	},
	setResolution: function(store, options) {
		store.baseParams.resolution = this.map.getResolution();
		this.destroyFeatures();
	},
	afterLoad: function(store, records, options) {
		try {
		var vectorLayer = this.map.getLayerByName("Vector Features");
		vectorLayer.setVisibility(true);
		
		if (this.features) {
			vectorLayer.removeFeatures(this.features);
			this.destroyFeatures();
		}
		
		// 得到表 HELEN_EDIT 中 gid 和 the_geom 的映射数组
		var geometries = {};
		for (var i in options.geometries) {
			geometries[i] = this.awp_wkt.read(options.geometries[i]);
		}
		
		// 求取最大边界
		this.features = [];
		var maxBounds = new OpenLayers.Bounds();
		for (var i = 0; i < records.length; i++) {
			var record = records[i], feature = null;	// feature = null 确保每行求取 feature 的结果不影响下一行，切忌
			
			if (record.data.the_geom) {// 如果记录有 the_geom 字段，则创建地理数据
				feature = this.awp_wkt.read(record.data.the_geom);
				feature.fid = this.layerId + '.' + record.data.gid;
			} else if (geometries[record.data.geom_id]) {// 如果记录有 geom_id 字段，则去映射数组中寻找地理数据
				feature = geometries[record.data.geom_id];
				feature.fid = this.layerId + '.' + record.data.geom_id;
			} 
			
			if (feature) {
				if (!feature.attributes.records) {
					feature.attributes.records = [];	// 数组 feature.attributes.records 保存引用此地理数据的多条记录
				}
				feature.attributes.records.push(record);
				feature.attributes.layer = this;
				record.feature = feature;
				
				var existing = false;
				for (var j = 0, f; f = this.features[j]; j++) {
					if (f == feature) {
						existing = true;
						break;
					}
				}
				if (!existing) this.features.push(feature);
				
				maxBounds.extend(feature.geometry.getBounds());
			}
		}
		
		// 有地理数据则缩放平移至适合大小和位置，没有则返回初始视点
		if (this.features.length != 0) {
			if (maxBounds.getWidth() != 0) {
				var zoomLevel = this.map.getZoomForExtent(maxBounds) - 1;
				if (zoomLevel != this.map.getZoom()) {
					this.map.setCenter(maxBounds.getCenterLonLat(), zoomLevel);
				} else {
					this.map.setCenter(maxBounds.getCenterLonLat());
				}
			} else {
				this.map.setCenter(maxBounds.getCenterLonLat());
			}
			vectorLayer.addFeatures(this.features);
		} else {
			var controlSearch = this.map.getControlsByClass('AWP.Control.Search')[0];
			if (controlSearch.searchMethod == 'keywords') {
				this.showHome();
			}
		}
		} catch (e) {
			;// 如果有异常抛出而不捕获，会影响后面的注册事件，比如 mask 会停留不取消
		}
	},
	/**
	 * 当鼠标悬浮 feature 之上，或者 feature 被选中时，相应设置表格中记录行的状态
	 */
	selectRowByFeature: function(ee) {
		if (this.awp_grid) {
			var record = ee.feature.attributes.record;		// feature 对应的行记录 
			var records = ee.feature.attributes.records;	// feature 对应的多行记录
			var index, indexes = {};
			if (record) {
				index = this.awp_grid.store.indexOf(record);
			} else if (records) {
				for (var i = 0, len = records.length; i < len; i++) {
					indexes[this.awp_grid.store.indexOf(records[i])] = true;
				}
			}
			
			var view = this.awp_grid.getView();
			for (var i = 0, len = this.awp_grid.store.getCount(); i < len; i++) {
				if (record && i == index) {
					view.onRowSelect(i);
				} else if (records && indexes[i]) {
					view.onRowSelect(i);
				} else {
					view.onRowDeselect(i);
				}
			}
		}
	},
	unselectRowByFeature: function(ee) {
		if (this.awp_grid) {
			var record = ee.feature.attributes.record;
			var records = ee.feature.attributes.records;
			var index, indexes = {};
			if (record) {
				index = this.awp_grid.store.indexOf(record);
			} else if (records) {
				for (var i = 0, len = records.length; i < len; i++) {
					indexes[this.awp_grid.store.indexOf(records[i])] = true;
				}
			}
			
			var view = this.awp_grid.getView();
			for (var i = 0, len = this.awp_grid.store.getCount(); i < len; i++) {
				if (record && i == index) {
					view.onRowDeselect(i);
				} else if (records && indexes[i]) {
					view.onRowDeselect(i);
				}
			}
		}
	},
	
	
	clearFeatures: function() {
		this.map.getControlsByClass('AWP.Control.SelectFeature')[0].unselectAll();
		this.destroyFeatures();
		
		this.awp_grid.destroy();
		this.awp_store.destroy();
		
		this.awp_tab = null;
		this.awp_grid = null;
		this.awp_store = null;
		
		// 关闭 tab 标签后，回到初始视点
		this.showHome();
	},
	destroyFeatures: function() {
		if (this.features) {
			for (var i = 0, len = this.features.length; i < len; i++) {
				var feature = this.features[i];
				if (feature.attributes.record) {
					feature.attributes.record.feature = null;
					feature.attributes.record = null;
				}
				feature.attributes.layer = null;
				feature.destroy();
				this.features[i] = null;
			}
			this.features = null;
		}
	},
	beforeRefresh: function() {
		this.map.getControlsByClass('AWP.Control.SelectFeature')[0].unselectAll();
		this.destroyFeatures();
	},
	
	
	displayFeatures: function(features) {
		//var vectorLayer = this.map.getLayerByName("Selection Features");
		var vectorLayer = this.map.getLayerByName("Vector Features");
		vectorLayer.setVisibility(true);
		//vectorLayer.destroyFeatures();
		
		/**/
		if (this.features) {
			vectorLayer.removeFeatures(this.features);
			this.destroyFeatures();
		}
		
		var feature, maxBounds = new OpenLayers.Bounds();
		for (var i = 0; i < features.length; i++) {
			feature = features[i];
			feature.attributes.layer = this;
			maxBounds.extend(feature.geometry.getBounds());
		}
		this.features = features;
		
		if (features.length != 0) {
			if (maxBounds.getWidth() != 0) {
				var zoomLevel = this.map.getZoomForExtent(maxBounds) - (features.length == 1 ? 6 : 1);
				if (zoomLevel != this.map.getZoom) this.map.setCenter(maxBounds.getCenterLonLat(), zoomLevel);
			}
			vectorLayer.addFeatures(features);
		}
	},
	/**
	 * 如果本行记录有 record.feature，那么在 feature 中记录 record，如果 feature 是点，则执行
	 *  clickFeature 点击事件，否则刷新 feature
	 * 用于响应 AWP.Layer.Grid 的 rowselect 事件，在 AWP.Layer.Grid 初始化时注册
	 * 	sm.addListener('rowselect', layer.onRowSelect, layer);
	 */
	onRowSelect: function(sm, rowIndex, record) {
		if (record.feature) {
			var bounds = record.feature.geometry.getBounds();
			record.feature.attributes.record = record;
			
			var controlSelectFeature = this.map.getControlsByClass('AWP.Control.SelectFeature')[0];
			if (bounds.getWidth() != 0) {
				var zoomLevel = this.map.getZoomForExtent(bounds) - 1;
				if (zoomLevel != this.map.getZoom) {
					this.map.setCenter(bounds.getCenterLonLat(), zoomLevel);
					// 在新的缩放级别下重新获取 feature
					controlSelectFeature.refreshFeature(record.feature);
				}
			} else {
				controlSelectFeature.clickFeature(record.feature);
			}
		}
	},
	/**
	 * 如果本行记录有 record.feature，那么执行 outFeature 鼠标移出事件
	 * 用于响应 AWP.Layer.Grid 的 rowdeselect 事件，在 AWP.Layer.Grid 初始化时注册
	 * 	sm.addListener('rowdeselect', layer.onRowDeselect, layer);
	 */
	onRowDeselect: function(sm, rowIndex, record) {
		var selectFeature = this.map.getControlsByClass('AWP.Control.SelectFeature')[0];
		if (record.feature) {
			selectFeature.outFeature(record.feature);
		}
	},
	showHome: function() {
		var center = (AWP.cfg.defaultCenter || this.map.defaultCenter);
		var zoomLevel = AWP.cfg.defaultZoomLevel || this.defaultZoomLevel;
		this.map.setCenter(center, zoomLevel);
	},
	showAllFeatures: function() {
		var vectorLayer = this.map.getLayerByName("Vector Features");
		
		if (this.features.length != 0) {
			var maxBounds = new OpenLayers.Bounds();
			for (var i = 0; i < this.features.length; i++) {
				var feature = this.features[i];
				if (feature) {
					maxBounds.extend(feature.geometry.getBounds());
				}
			}
			
			var zoomLevel = this.map.getZoomForExtent(maxBounds) - 1;
			if (zoomLevel != this.map.getZoom) this.map.setCenter(maxBounds.getCenterLonLat(), zoomLevel);
			
			var controlSelectFeature = this.map.getControlsByClass('AWP.Control.SelectFeature')[0];
			var selectedFeature = controlSelectFeature.selectedFeature;
			
			if (selectedFeature && selectedFeature.popup) {
				this.map.removePopup(selectedFeature.popup);
				selectedFeature.popup.destroy();
				selectedFeature.popup = null;
				
				controlSelectFeature.select(selectedFeature);
			}
		}
	},
	createPopupOnClick: function(feature) {
		var data = feature.attributes.record.data;
		
		if (this.layerId == 'station_join2') {
			var contentHTML = [
				'<table width="290" border="0"><tr><td valign="top">',
				  '<table width="290" border="0" cellspacing="1" bgcolor="silver">',
					'<tr bgcolor="white">',
					  '<td class="awp-txt-little awp-txt-bold" style="padding:2px">' + data.stn_name + '</td>',
					'</tr>',
				    '<tr bgcolor="white">',
					  '<td class="awp-txt-little awp-txt-bold" style="padding:2px">',
					    '<select id="realtime-datatypes" onchange="switch_flash(this)" style="width: 230px"></select>&nbsp;&nbsp;',
					    '<a href="javascript:void(0)" onclick="return AWP.Layer._export(\'',
						data.aenv_stati, '\', this)"><img src="' + AWP.cfg.baseURL + 'image/csv.png" width="15" height="15"  style="vertical-align:bottom" /></a>&nbsp;',
					    '<a href="javascript:void(0)" onclick="return AWP.Layer._export(\'',
						data.aenv_stati, '\', this, \'png\')"><img src="' + AWP.cfg.baseURL + 'image/print.png" width="15" height="15"  style="vertical-align:bottom" /></a>',
						'</td>',
					'</tr>',
					'<tr bgcolor="white">',
					  '<td class="awp-txt-little awp-txt-bold" style="padding:2px">',
					    '<a href="javascript:void(0)" onclick="AWP.Layer.getRealtimeData(\'',
						data.aenv_stati, '\', \'6h\')">6h</a>&nbsp;',
					    '<a href="javascript:void(0)" onclick="AWP.Layer.getRealtimeData(\'',
						data.aenv_stati, '\', \'1d\')">1d</a>&nbsp;',
						'<a href="javascript:void(0)" onclick="AWP.Layer.getRealtimeData(\'',
						data.aenv_stati, '\', \'5d\');">5d</a>&nbsp;',
						'from:<input type="text" id="realtime-start" size="12"',
						' onclick="AWP.DatePicker.show(\'realtime-start\')" />&nbsp;',
						'to:<input type="text" id="realtime-end" size="12"',
						' onclick="AWP.DatePicker.show(\'realtime-end\')" />&nbsp;',
					    '<a href="javascript:void(0)" onclick="AWP.Layer.getRealtimeData(\'',
						data.aenv_stati, '\', \'from-to\')">Go</a>&nbsp;',
					  '</td>',
					'</tr>',
				  '</table></td></tr><tr><td id="realtime-graph">',
				  '</td></tr></table>'
			].join('');
			
			var popup = new AWP.Popup(
				null, 
				feature.geometry.getBounds().getCenterLonLat(),
				new OpenLayers.Size(300, 200),
				contentHTML,
				null, 
				true
			);
		} else {
			var contentHTML = ['<table width="100%" border="0" cellpadding="3" cellspacing="1" bgcolor="silver">'];
			for (var key in data) {
				if (key == 'the_geom') continue;
				contentHTML = contentHTML.concat([
					'  <tr bgcolor="white">',
					'    <td class="awp-txt-little awp-txt-bold">' + key + ':</td>',
					'    <td class="awp-txt-little">' + data[key] + '</td>',
					'  </tr>',
				]);
			}
			contentHTML.push('</table>');
			
			var popup = new AWP.Popup(
				null, 
				feature.geometry.getBounds().getCenterLonLat(),
				new OpenLayers.Size(300, 150),
				contentHTML.join(''),
				null, 
				true
			);
		}
		
		return popup;
	},
	onCreatePopupOnClick: function(feature) {
		var data = feature.attributes.record.data;
		
		if (this.layerId == 'station_join2') {
			AWP.Layer.getRealtimeData(data.aenv_stati, '6h');
		}
	},
	setGEVisibility: function(visible) {
		//OpenLayers.Layer.WMS.prototype.setVisibility.call(this, visible);
		if (this.map.googleEarth) {
			this.map.googleEarth.setLayerVisibility(this, visible);
		}
	},
    CLASS_NAME: "AWP.Layer"
});

AWP.Layer.array = [];
AWP.Layer.items = {};

AWP.Layer.overFeature = function(fid) {
	var selectFeature = AWP.map.getControlsByClass('AWP.Control.SelectFeature')[0];
	
	var feature = null;
	for (var i = selectFeature.layer.features.length - 1; i >= 0; --i) {
		feature = selectFeature.layer.features[i];
		if (fid == feature.fid) break;
	}
	
	if (feature) {
		selectFeature.overFeature(feature);
	}
}
AWP.Layer.outFeature = function(fid) {
	var selectFeature = AWP.map.getControlsByClass('AWP.Control.SelectFeature')[0];
	
	var feature = null;
	for (var i = selectFeature.layer.features.length - 1; i >= 0; --i) {
		feature = selectFeature.layer.features[i];
		if (fid == feature.fid) break;
	}
	
	if (feature) {
		selectFeature.outFeature(feature);
	}
}

function switch_flash(sel) {
	if (!sel.value) return
	var div = document.getElementById(sel.value);
	if (div) {
		div.style.display = 'block';
	
		var divs = div.parentNode;
		for (var i = 0; i < divs.childNodes.length; i++) {
			var d = divs.childNodes[i];
			if (div != d) {
				d.style.display = 'none';
			}
		}
	}
}
AWP.Layer.range = '';
AWP.Layer.getRealtimeData = function(station_strid, range) {
	AWP.Layer.range = range;
	
	var date_from = document.getElementById('realtime-start').value;
	var date_to = document.getElementById('realtime-end').value;
	
	OpenLayers.Request.GET({
		url: AWP.cfg.serviceURL
			+ 'action=getRealtimeData'
			+ '&station=' + station_strid
			+ '&range=' + range
			+ '&from=' + date_from
			+ '&to=' + date_to
			+ '&format=json',
		success: function(response) {
			try {
				var json = eval('(' + response.responseText + ')');
			} catch (e) {
				alert(e + '\n\n' + response.responseText);
				return
			}
			
			try {
				AWP.Layer.chart(json);
			} catch (e) {
				alert(e);
				return
			}
		},
		failure: function() {
			alert('sorry')
		}
	});	
}
AWP.Layer._export = function(station_strid, a, image) {
	if (image == 'png') a.target = '_blank';
	
	var date_from = document.getElementById('realtime-start').value;
	var date_to = document.getElementById('realtime-end').value;
	
	a.href = [
		AWP.cfg.baseURL, "realtime/export.php?station=", station_strid,
		"&range=", AWP.Layer.range,	'&from=', date_from, '&to=', date_to,
		"&image=", image
	].join('');
}
AWP.Layer.chart = function(json) {
	var stations = json.stations;
	
	var data = {}, data_types = {};
	var not = {id:1,text_id:1,basin_id:1,infotype_id:1,station:1,date_and_time:1};
	
	for (var i = 0, len = stations.length; i < len; i++) {
		var row = stations[i];
		for (var j = 0, cnt = row.records.length; j < cnt; j++) {
			var r = row.records[j];
			var t = r['date_and_time'];
			var y = parseInt(t.substr(0, 4), 10);
			var m = parseInt(t.substr(5, 2), 10);
			var d = parseInt(t.substr(8, 2), 10);
			var h = parseInt(t.substr(11, 2), 10);
			var n = parseInt(t.substr(14, 2), 10);
			var s = parseInt(t.substr(17, 2), 10);
			var time = (new Date(y, m - 1, d, h, n, s)).getTime();
			for (var key in r) {
				if (!not[key]) {
					var category = key + '(' + row.basin_id + ',' + row.infotype_id + ')';
					if (!data[category]) data[category] = {};
					if (!data_types[category]) {
						data_types[category] = key + ' - ' + row.basin_descriptor + '(' + row.basin_id + '):'
							+ row.infotype_descriptor + '(' + row.infotype_id + ')';
					}
					data[category][time] = parseFloat(r[key]);
				}
			}
		}
	}
	
	ua = navigator.userAgent.toLowerCase();
	for (var type in data_types) {
		var opt = document.createElement('option');
		opt.value = type;
		opt.text = data_types[type];
		/**
		 * IE 7 needs "-1", FF needs "null"
		 */
		if (ua.indexOf("msie") != -1 ) {
			document.getElementById('realtime-datatypes').add(opt, -1);
		} else {
			document.getElementById('realtime-datatypes').add(opt, null);
		}
	}
	
	var chartsHTML = ['<div style="width: 295px; height: 130px; overflow:hidden">'];
	for (var category in data) {
		var xml = [], categories = [], dataset = [];
		
		var min_time = null, max_time = null, min_var = null, max_var = null;
		for (var time in data[category]) {
			var value = data[category][time];
			
			min_time = min_time == null ? time : Math.min(min_time, time);
			max_time = max_time == null ? time : Math.max(max_time, time);
			min_var = min_var == null ? value : Math.min(min_var, value);
			max_var = max_var == null ? value : Math.max(max_var, value);
		}
		
		var list = [];
		for (time = min_time; time < max_time; time += 900000) {
			list.push([time, data[category][time] || '']);
		}
		
		dataset = dataset.concat([
			"<dataset seriesName='", category, "'",
			" color='1D8BD1'",
			" anchorSides='12'",
			" anchorRadius='3'",
			" anchorAlpha='30'",
			" anchorBorderColor='1D8BD1'",
			" anchorBgColor='1D8BD1'>",
		]);
		
		var space = (max_time - min_time) / 60000 / 12;
		for (var i = 0, len = list.length; i < len; i++) {
			var t = new Date(list[i][0]), value = list[i][1];
			var y = t.getFullYear(), m = t.getMonth() + 1, d = t.getDate(), h = t.getHours(), n = t.getMinutes();
			
			name = space;
			var showName = 1;
			if (space > 120) {
				if (n != 0 || h % 6 != 0) {
					showName = 0;
				} else {
					name = h ? h + ':00' : [m, '-', d].join('');
				}
			} else if (space > 30) {
				if (n != 0) {
					showName = 0;
				} else {
					name = h ? h + ':00' : [m, '-', d].join('');
				}
			} else {
				if (i == 0 || i == len - 1 || (h == 0 && n == 0)) {
					name = [m, '-', d].join('');
				} else {
					name = [h < 10 ? '0' + h : h, ':', n ? n : '00'].join('');
				}
			}
			
			categories.push([
				"<category",
				" showName='", showName, "'",
				" hoverText='", y, '-', m, '-', d, ' ', h, ':', n, "'",
				" name='" + name + "' />"
			].join(''));
			
			dataset.push("<set value='" + value + "' />");
		}
		dataset.push("</dataset>");
		
		if (min_var == max_var) {
			min_var = Math.min(max_var * 0.99, max_var * 1.01);
			max_var = Math.max(max_var * 0.99, max_var * 1.01);
		} else {
			min_var = min_var - (max_var - min_var) * 0.2;
			max_var = max_var + (max_var - min_var) * 0.2;
		}
		
		xml = xml.concat(["<graph caption='' subcaption=''",
			" hovercapbg='FFECAA' hovercapborder='F47E00'",
			" chartLeftMargin='5'",
			" chartRightMargin='5'",
			" chartTopMargin='5'",
			" chartBottomMargin='5'",
			" showAnchors='", len > 48 ? 0 : 1, "'",
			" lineThickness='1'",
			" showShadow='0'",
			" formatNumberScale='2' decimalPrecision='3' showvalues='0'",
			" numdivlines='4' numVdivlines='0'",
			" yAxisName='realtime data'",
			" yaxisminvalue='", min_var, "'",
			" yaxismaxvalue='", max_var, "'",
			" rotateNames='1'>",
			"<categories>"]);
		xml = xml.concat(categories);
		xml.push("</categories>");
		xml = xml.concat(dataset);
		xml.push("</graph>");
		
		var w = 300, h = 135;
		var chart = new FusionCharts(AWP.cfg.FusionChart, "ChartId", w, h);
		chart.setDataXML(xml.join(''));
		chartsHTML.push('<div id="' + category + '" style="position: relative; display: none">');
		chartsHTML.push(chart.getSWFHTML());
		chartsHTML.push('</div>');
	}
	chartsHTML.push('</div>');
	
	var td = document.getElementById('realtime-graph');
	td.innerHTML = chartsHTML.join('');
	
	switch_flash(document.getElementById('realtime-datatypes'));
}















