AWP.User = function(user) {
	Ext.apply(this, user);
}
Ext.extend(AWP.User, Ext.util.Observable, {
	categoryTree: null,
	categoryStyleMap: null,
	currentNode: null,
	featureList: null,
	
	tinymceSettings: {
		// General
		directionality: "ltr",
		editor_selector : "mce_editable",
		language : "en",
		mode : "specific_textareas",
		skin : "default",
		theme : "advanced",
		// Cleanup/Output
		cleanup : true,
		cleanup_on_startup : false,
		entity_encoding : "raw",
		extended_valid_elements : "hr[id|title|alt|class|width|size|noshade],img[class|src|border=0|alt|title|hspace|vspace|width|height|align|onmouseover|onmouseout|name],a[class|name|href|target|title|onclick|rel]",
		force_br_newlines : "false", force_p_newlines : "true", forced_root_block : 'p',
		invalid_elements : "applet",
		// URL
		relative_urls : true,
		remove_script_host : false,
		document_base_url : "http://localhost/joomla/www/",
		// Layout
		content_css : "http://localhost/joomla/www/templates/rhuk_milkyway/css/template.css, http://localhost/joomla/www/templates/system/css/editor.css",
		// Advanced theme
		theme_advanced_toolbar_location : "top",
		theme_advanced_toolbar_align : "left",
		theme_advanced_source_editor_height : "550",
		theme_advanced_source_editor_width : "750",
		theme_advanced_statusbar_location : "bottom", theme_advanced_path : true
	},
	isAdmin: function() {
		return this.usertype == 'Administrator'
			|| this.usertype == 'Manager'
			|| this.usertype == 'Super Administrator';
	},
	addContent: function(el) {
		if (this.currentNode) {
			alert('Please finish previous operation first.');
			return
		}
		
		document.getElementById('btn_modify_feature').value = 'Create';
		document.forms['user-content'].title.value = '';
		if (this.tinymce) this.tinymce.setContent('');
		
		this.contentWindow = this.getContentWindow();
		this.contentWindow.show(el);
		
		document.getElementById('user-content-el').style.display = '';
		this.getEditor();
	},
	toggleUserFeature: function(node) {
		var vlayer = AWP.map.getLayerByName('Editable');
		
		if (this.currentNode && this.currentNode != node) {
			this.currentNode.attributes.outstanding = false;
		}
		
		if (node) {
			var node_attr = node.attributes;
			var these_features = [], those_features = [];
			
			if (!vlayer.tmpFeatures) {
				vlayer.tmpFeatures = vlayer.features.slice();
			}
			for (var i = 0, len = vlayer.tmpFeatures.length; i < len; i++) {
				var feature_attr = vlayer.tmpFeatures[i].attributes;
				/**
				 * 如果当前 feature(s) 未突出显示，那么只把当前 feature(s) 作为 these_features 准备显示，
				 * 否则所有 feature(s) 作为 these_features，准备显示
				 */
				if (!node_attr.outstanding && feature_attr.content_id != node_attr.content_id) {
					those_features.push(vlayer.tmpFeatures[i]);
				} else {
					these_features.push(vlayer.tmpFeatures[i]);
				}
			}
			
			vlayer.removeFeatures(vlayer.features);
			vlayer.addFeatures(these_features);
			node_attr.outstanding = !node_attr.outstanding;
			
			if (these_features.length == 0) {
				alert('This content has no associated feature(s)');
			} else {
				var bounds = new OpenLayers.Bounds();
				for (var i = 0, len = these_features.length; i < len; i++) {
					bounds.extend(these_features[i].geometry.getBounds());
				}
				
				var map = vlayer.map;
				var lonlat = bounds.getCenterLonLat();
				var zoomLevel = map.getZoomForExtent(bounds);
				
				// 如果目标需要适当放大
				if (bounds.getWidth() != 0 && zoomLevel < map.getZoom()) {
					map.zoomTo(zoomLevel);
				}
				// 如果目标不在当前范围内
				if (!map.getExtent().scale(map.panRatio).containsLonLat(lonlat)) {
					var maxBounds = bounds.clone();
					for (var i = 0, len = those_features.length; i < len; i++) {
						maxBounds.extend(those_features[i].geometry.getBounds());
					}
					var maxZoomLevel = map.getZoomForExtent(maxBounds)
					lonlat = maxBounds.getCenterLonLat();
					
					if (map.getZoom() != maxZoomLevel) {
						map.zoomTo(maxZoomLevel);
					}
				}
				// 先平移
				map.panTo(lonlat);
				// 再缩放
				if (bounds.getWidth() != 0 && (map.getZoom() > zoomLevel || map.getZoom() < zoomLevel - 2)) {
					this.mapMoveEndZoomLevel = zoomLevel;
					map.events.register("moveend", this, this.mapMoveEnd);
				}
			}
		} else {
			vlayer.eraseFeatures(vlayer.features);
		}
		
		this.currentNode = node;
	},
	getEditor: function() {
		if (!this.tinymce) {
			this.tinymceSettings = tinymce.extend({
				language : "en",
				strict_loading_mode : document.contentType == 'application/xhtml+xml'
			}, this.tinymceSettings);
			this.tinymce = new tinymce.Editor('customer-content', this.tinymceSettings);
			this.tinymce.render(1);
			
			document.getElementById('user-content-el').style.display = '';
		}
		
		return this.tinymce;
	},
	getContentWindow: function(node) {
		if (!this.contentWindow) {
			var div = document.getElementById('user-content-el');
			div.style.position = 'static';
			div.style.left = '0px';
			this.contentWindow = new Ext.Window({
				contentEl: 'user-content-el',
				layout: 'fit',
				width: 500,
				height: 500,
				minWidth: 95,
				minHeight: 0,
				closeAction: 'hide',
				plain: true,
		
				buttons: [{
					text: 'Reject/Approve',
					visible: false,
					scope: this,
					handler: this.approveContent
				}, {
					text: 'Submit',
					scope: this,
					handler: this.saveContent
				}, {
					text: 'Close',
					scope: this,
					handler: function() {
						var win = this.contentWindow;
						if (win.minimized) {
							var config = win.initialConfig;
							win.setSize(config.width, config.height);
							
							document.getElementById('draw_feature_tool').style.display = 'none';
							win.minimized = false;
						} else {
							win.hide();
						}
					}
				}]
			});
			
			this.contentWindow.on('hide', function() {
				var vlayer = AWP.map.getLayerByName('Editable');
				for (var i = 0, len = vlayer.features.length; i < len; i++) {
					var feature = vlayer.features[i];
					var category_id = feature.attributes.category_id;
					vlayer.drawFeature(feature, this.categoryStyleMap[category_id]);
				}
				
				AWP.map.getControlsByClass('AWP.Control.ModifyFeature')[0].deactivate();
				AWP.map.getControlsByClass('AWP.Control.DrawFeature')[0].deactivate();
				AWP.map.getControlsByClass('AWP.Control.DrawFeature')[1].deactivate();
				AWP.map.getControlsByClass('AWP.Control.DrawFeature')[2].deactivate();
				
				this.updateNode(this.currentNode);
				this.currentNode = null;
			}, this);
			
			this.contentWindow.on('minimize', function() {
				var config = this.initialConfig;
				this.setSize(config.minWidth, config.minHeight);
				this.minimized = true;
			});
			
			Ext.get('btn_modify_feature').on("click", this.modifyFeature, this);
			
			var control = AWP.map.getControlsByClass('AWP.Control.ModifyFeature')[0];
			//control.layer.events.register("featureunselected", this, this.saveFeature);
			control.events.register("featuremodified", this, this.saveFeature);
			
			var controlDrawFeatures = AWP.map.getControlsByClass('AWP.Control.DrawFeature');
			controlDrawFeatures[0].events.register("featureadded", this, this.saveFeature);
			controlDrawFeatures[1].events.register("featureadded", this, this.saveFeature);
			controlDrawFeatures[2].events.register("featureadded", this, this.saveFeature);
		}
		
		if (this.isAdmin() && node) {
			this.contentWindow.buttons[0].show();
			this.contentWindow.buttons[0].setText(node.attributes.approved == 1 ? 'Unpublish' : 'Publish');
		} else {
			this.contentWindow.buttons[0].hide();
		}
		
		return this.contentWindow;
	},
	saveContent: function() {
		var form = document.forms['user-content'];
		
		var title = form.title.value;
		var text = this.getEditor().getContent();
		var category = document.getElementById('user-category').value;
		var content_id = this.currentNode ? this.currentNode.attributes.content_id : 0;
		
		if (category == "") {
			alert("Please choose a category");
			return
		} else if (title == "") {
			alert("Content must have a Title");
			return
		} else if (text == "") {
			alert("Content must have some text");
			return
		}
		
		if (form.kml_file.value) {
			form.action = AWP.cfg.serviceURL
				+ '?action=AWP.saveUserContent'
				+ '&content_id=' + content_id
				+ '&title=' + title
				+ '&content=' + text
				+ '&user_id=' + this.id
				+ '&category=' + category;
			form.submit();
		} else {
			Ext.Ajax.request({
				url: AWP.cfg.serviceURL,
				params: {
					action: 'AWP.saveUserContent',
					content_id: content_id,
					title: title,
					content: text,
					user_id: this.id,
					category: category,
					format: 'json'
				},
				scope: this,
				success: function(response, options) {
					try {
						var json = eval('(' + response.responseText + ')');
					} catch (e) {
						alert(e + '\n\n' + response.responseText);
						return
					}
					var result = json;
					
					if (result) {
						this.currentNode.attributes.title = result.title;
						this.currentNode.attributes.text = result.text;
						this.currentNode.attributes.category_id = result.category_id;
						this.currentNode.setText(result.text);
						
						if (!this.currentNode.rendered) {
							var categoryNode = this.categoryTree.getNodeById('category_' + result.category_id);
							if (!categoryNode.expanded) categoryNode.expand();
							categoryNode.appendChild(this.currentNode);
						}
						
						this.contentWindow.hide();
					} else {
						alert('Failed to save content');
					}
				}
			});
		}
	},
	selectedContentId: 0,
	toggleUserFeatureByContentId: function(content_id) {
		var vlayer = AWP.map.getLayerByName('Editable');
		
		/**
		 * 判断所属 content_id 的 features 是否已突出显示
		 */
		var content_id_hash = {}, content_id_list = [];
		for (var i = 0, len = vlayer.features.length; i < len; i++) {
			var cid = vlayer.features[i].attributes.content_id;
			if (!content_id_hash[cid]) {
				content_id_hash[cid] = true;
				content_id_list.push(cid);
			}
		}
		var focus = content_id_list.length == 1 && content_id_list[0] == content_id;
		this.selectedContentId = focus ? 0 : content_id;
		
		/**
		 * 决定显示哪些 features
		 */
		
		if (!vlayer.tmpFeatures) {
			vlayer.tmpFeatures = vlayer.features.slice();
		}
		var focus_features = [], maxBounds = new OpenLayers.Bounds();
		for (var i = 0, len = vlayer.tmpFeatures.length; i < len; i++) {
			var feature = vlayer.tmpFeatures[i];
			/**
			 * 如果当前 content_id 的 feature(s) 已突出显示，那么显示所有的 features
			 * 否则显示 content_id 的 feature(s)
			 */
			if (focus || feature.attributes.content_id == content_id) {
				focus_features.push(feature);
			}
			maxBounds.extend(feature.geometry.getBounds());
		}
		
		/**
		 * 清空 mouseoverFeature, selectFeature, selectFeatures
		 */
		var controlSelectFeature = AWP.map.getControlsBy('id', 'editable_selectFeature')[0];
		controlSelectFeature.unselectAll();
		
		vlayer.removeFeatures(vlayer.features);
		vlayer.addFeatures(focus_features);
		
		if (focus_features.length == 0) {
			alert('This content has no associated feature(s)');
		} else {
			var bounds = new OpenLayers.Bounds();
			for (var i = 0, len = focus_features.length; i < len; i++) {
				bounds.extend(focus_features[i].geometry.getBounds());
			}
			
			var map = vlayer.map;
			var lonlat = bounds.getCenterLonLat();			// 目标中心点
			var zoomLevel = map.getZoomForExtent(bounds);	// 目标缩放级别
			
			// 如果目标需要适当放大视野，先放大
			if (bounds.getWidth() != 0 && zoomLevel < map.getZoom()) {
				map.zoomTo(zoomLevel);
			}
			// 如果目标不在当前范围内
			if (!map.getExtent().scale(map.panRatio).containsLonLat(lonlat)) {
				var maxZoomLevel = map.getZoomForExtent(maxBounds)
				// 如果当前缩放级别不是最大级别视野
				if (map.getZoom() != maxZoomLevel) {
					map.zoomTo(maxZoomLevel);
				}
			}
			// 先平移
			map.panTo(lonlat);
			// 再缩放
			if (bounds.getWidth() != 0 && (map.getZoom() > zoomLevel || map.getZoom() < zoomLevel - 1)) {
				this.mapMoveEndZoomLevel = zoomLevel;
				map.events.register("moveend", this, this.mapMoveEnd);
			}
		}
	},
	modifyFeature: function() {
		if (this.currentNode) this.currentNode.attributes.outstanding = false;
		
		this.contentWindow.minimize();
		this.toggleUserFeature(this.currentNode);
		
		document.getElementById('draw_feature_tool').style.display = '';
		var control = AWP.map.getControlsByClass('AWP.Control.ModifyFeature')[0];
    	control.activate();
	},
	saveFeature: function(evt) {
		var feature = evt.feature;
		/**
		 * to void error by mouse over event
		 */
		feature.attributes.category = 'customer';
		
		var category;
		if (this.currentNode) {
			category = this.currentNode.attributes.category_id;
		} else {
			category = document.getElementById('user-category').value;
		}
		if (this.categoryStyleMap[category]) {
			var vlayer = AWP.map.getLayerByName('Editable');
			vlayer.drawFeature(feature, this.categoryStyleMap[category]);
		}
		
		var kml = (new AWP.Format.KML()).write(feature);
		var type = feature.geometry.CLASS_NAME.substring(feature.geometry.CLASS_NAME.lastIndexOf(".") + 1);
		var content_id = this.currentNode ? this.currentNode.attributes.content_id : 0;
		
		OpenLayers.Request.GET({
			url: AWP.cfg.serviceURL
				+ '?action=AWP.saveKML&format=json'
				+ '&gid=' + feature.fid
				+ '&content_id=' + content_id
				+ '&user_id=' + this.id
				+ '&geom_type=' + type.toLowerCase()
				+ '&kml=' + kml,
			success: function(feature) {
				return function(response) {
					this.saveFeatureSuccess(response, feature);
				}
			} (feature),
			failure: this.saveFeatureFailure,
			scope: this
		});
    },
    saveFeatureSuccess: function(response, feature) {
    	try {
    		var json = eval('(' + response.responseText + ')');
    	} catch (e) {
    		alert(e + '\n\n' + response.responseText);
    	}
    	
    	var content_id = json.content_id;
    	
    	feature.fid = json.gid;
		feature.attributes.content_id = content_id;
		
		if (!this.currentNode) {
			this.currentNode = new AWP.Layer.TreeNode({
				content_id: content_id,
				approved: 0,
				leaf: true,
				category: 'customer'
			});
		}
    },
    saveFeatureFailure: function() {
    	alert('Failed to save feature')
    },
    deleteFeature: function(feature) {
		OpenLayers.Request.GET({
			url: AWP.cfg.serviceURL
				+ '&action=deleteCustomerContentFeature'
				+ '&gid=' + feature.fid
				+ '&user_id=' + this.id,
			success: function(feature) {
				return function(response) {
					this.deleteFeatureSuccess(response, feature);
				}
			} (feature),
			failure: function() {
				alert('Failed to delete customer content feature');
			},
			scope: this
		});
    },
    deleteFeatureSuccess: function(response, feature) {
		try {
			var json = eval('(' + response.responseText + ')');
		} catch (e) {
			alert(e + '\n\n' + response.responseText);
		}
    	if (json.resource == true) {
    		var vlayer = AWP.map.getLayerByName('Editable');
			vlayer.destroyFeatures([feature]);
    	}
    },
    updateNode: function(node) {
    	if (!node) return
    	
		Ext.Ajax.request({
			url: AWP.cfg.serviceURL,
			params: {
				action: 'AWP.getFeatureByContent',
				content_id: node.attributes.content_id || 0,
				format: 'json'
			},
			success: function(response, options) {
				try {
					var json = eval('(' + response.responseText + ')');
				} catch (e) {
					alert(e + '\n\n' + response.responseText);
				}
				
				var category_id, rows = json.result;
				
				for (var i = 0, len = rows.length; i < len; i++) {
					var row = rows[i];
					if (i == 0) {
						node.attributes.text = (row.title ? row.text : 'Untitled ' + row.id);
						node.attributes.approved = row.approved;
						node.attributes.content_id = row.content_id;
						category_id = row.category_id;
					}
				}
				
				if (category_id != node.attributes.category_id) {
					this.showCategories();
				} else {
					node.attributes.category_id = category_id;
					
					var format = new AWP.Format.KML(), features = [];
					for (var i in rows) {
						var row = rows[i];
						if (row.kml) {
							var feature = format.read(row.kml)[0];
							if (feature) {
								if (this.categoryStyleMap[row.category_id]) {
									feature.style = this.categoryStyleMap[row.category_id]
								}
								
								feature.fid = row.gid;
								for (var key in row) {
									if (key == 'kml') continue;
									feature.attributes[key] = row[key];
								}
								features.push(feature);
							}
						}
					}
					
					node.setText(node.attributes.text + ' [' + features.length + ']');
					node.ui.textNode.style.color = node.attributes.approved == 1 ? '#008000' : 'gray';
					node.ui.textNode.style.fontWeight = node.attributes.approved == 1 ? 'bold' : 'normal';
					
					var vlayer = AWP.map.getLayerByName('Editable'), old_features = [];
					for (var i = 0, len = vlayer.features.length; i < len; i++) {
						var feature_attr = vlayer.features[i].attributes;
						if (feature_attr.content_id == node.attributes.content_id) {
							old_features.push(vlayer.features[i]);
						}
					}
					vlayer.destroyFeatures(old_features);
					vlayer.addFeatures(features);
				}
			},
			scope: this
		});
    }
});
