AWP.Layer.Tree = function(config) {
	config = config || {};

	config.height 			= 'auto';
	config.border 			= false;
	config.showWmsLegend 	= true;

	if (config.category) {
		var category = config.category || '';
		config.model = this.buildLayersTreeModel(category);
	} else if (config.dataUrl) {
		/*this.loader.url = config.dataUrl;
		this.loader.createNode = function(attr){
			// apply baseAttrs, nice idea Corey!
			if (this.baseAttrs) Ext.applyIf(attr, this.baseAttrs);
			if (this.applyLoader !== false) attr.loader = this;
			if (typeof attr.uiProvider == 'string') {
			   attr.uiProvider = this.uiProviders[attr.uiProvider] || eval(attr.uiProvider);
			}
			if (attr.nodeType) {
				return new Ext.tree.TreePanel.nodeTypes[attr.nodeType](attr);
			} else {
				return attr.leaf ? new AWP.Layer.TreeNode(attr) : new AWP.Layer.AsyncTreeNode(attr);
			}
		}*/
	}

	config.listeners = {
		'click': this.onClickNode,
		'radiochange': this.onRadioChange,
		'checkchange': this.onCheckChange,
		'attributesclick': this.onAttributesClick
	}

	AWP.Layer.Tree.superclass.constructor.call(this, config);
}

Ext.extend(AWP.Layer.Tree, mapfish.widgets.LayerTree, {
	scale: null,
	initComponent: function() {
        this.eventModel = new AWP.Layer.TreeEventModel(this);
        mapfish.widgets.LayerTree.superclass.initComponent.call(this);

        this.addListener("checkchange", function checkChange(node, checked) {
            this._handleModelChange(node, checked);
        }, this);
        this.addListener("radiochange", function radioChange(node, checked) {
            this._handleModelChange(node, checked);
        }, this);

		if (typeof this.model == 'object' && this.model != null) {
			var root = {
				text: 'Root',
				draggable: false, // disable root node dragging
				id: 'source',
				children: this.model,
				leaf: false,
				uiProvider: AWP.Layer.RootTreeNodeUI
			};

			var rootNode = this.buildTree(root);
			this.setRootNode(rootNode);
		}
    },
	buildTree: function(attributes) {
		var node = new AWP.Layer.TreeNode(attributes);
		var cs = attributes.children;

		node.leaf = !cs;
		if (!cs) return node;

		for (var i = 0; i < cs.length; i++) {
			// XXX This index is sometimes undefined on IE for unknown reason
			if (!cs[i]) continue;
			node.appendChild(this.buildTree(cs[i]));
		}
		return node;
	},
    afterRender: function() {
        Ext.tree.TreePanel.superclass.afterRender.call(this);
		
        this.root.render();
		
        if (!this.rootVisible) {
            //this.root.renderChildren();
        }
    },
	onClickNode: function(node) {
		if (node.disabled) return false;
		
		if (node.childNodes.length) {
			node.toggle();
		} else {
			if (node.attributes.radio) {
				node.getUI().fireEvent('radiochange', node, true);
			} else {
				node.getUI().toggleCheck();
			}
		}
	},
	onRadioChange: function(node, checked) {
		var layer = node.attributes;
		// seawa layers are not base layers
		if (layer.category == 'seawa') return;

		if (checked) AWP.map.setBaseLayer(layer);
	},
	onCheckChange: function(node, checked){
		var layer = node.attributes;
		
		if (layer.category == 'customer') {
			AWP.userContent.onClickFrontTreeCategory(node.attributes.category_id, checked);
		} else if (layer instanceof AWP.Layer.Google) {
			if (checked) AWP.map.setBaseLayer(layer);
		} else if (layer instanceof AWP.Layer.Markers) {
			layer.setVisibility(checked);
		} else if (layer instanceof AWP.Layer) {
			var allSelected = true, pNode = node.parentNode, cs = pNode.childNodes;
			
			for (var i = 0, len = cs.length; i < len; i++) {
				allSelected &= cs[i].getUI().isChecked();
			}
			
			if (pNode.multi_layer && allSelected) {
				pNode.multi_layer.setVisibility(true);
				for (var i = 0, len = cs.length; i < len; i++) {
					cs[i].attributes.setVisibility(false);
				}
			} else {
				if (pNode.multi_layer) pNode.multi_layer.setVisibility(false);
				for (var i = 0, len = cs.length; i < len; i++) {
					cs[i].attributes.setVisibility(cs[i].getUI().isChecked());
				}
			}

			layer.setGEVisibility(checked);
			if (node.attributes.layerId == AWP.cfg.SEAWA_GE_DEFAULT_LAYER_ID) {
				AWP.map.getLayerByName(AWP.cfg.SEAWA_GE_DEFAULT_LAYER_ID + '_icon').setVisibility(checked);
			}
		} else {
			if (node.text == 'PFRA Watershed Boundaries') {
				var cs = node.childNodes;
				for (var i = 0, len = cs.length; i < len; i++) {
					cs[i].attributes.setVisibility(checked);
				}
			} else if (node.text == 'Toporama WMS') {
				var cs = node.childNodes;
				for (var i = 0, len = cs.length; i < len; i++) {
					cs[i].attributes.setVisibility(false);
				}
				if (checked) {
					if (!node.multi_layer) {
						node.multi_layer = new AWP.Layer({
							name: "OpenLayers WMS",
							layerId: "toporama-all",
							layers: "WMS-Toporama",
							server: AWP.cfg.LAYER_GROUP2,
							opacity: 0.7
						});
						AWP.map.addLayer(node.multi_layer);
					}
					node.multi_layer.setVisibility(true);
				} else {
					if (node.multi_layer) node.multi_layer.setVisibility(false);
				}

				if (node.attributes.category != 'seawa') node.multi_layer.setGEVisibility(checked);
			} else if (node.attributes.category == AWP.cfg.SEAWA) {
				var a		= node.attributes,
					layer	= AWP.map.getLayerByName(AWP.cfg.SEAWA_GE_DEFAULT_LAYER_ID + '_icon');
				
				for (var i = 0, marker; marker = layer.markers[i]; i++) {
					if (!a.basin_name || a.basin_name == marker.basin_name) {
						marker.display(checked);
					}
				}
			} else {
				var cs = node.childNodes;
				for (var i = 0, len = cs.length; i < len; i++) {
					cs[i].attributes.setVisibility(checked);
				}
			}
		}
	},
	onAttributesClick: function(node) {
		var layer = node.attributes;
		AWP.mainPanel.expandSouth(layer.findByKeywords, layer);
	},
	buildLayersTreeModel: function(category) {
		var treeModel = [], categories = AWP.cfg.CATEGORIES;

		for (var i = 0, len = category.length; i < len; i++) {
			treeModel.push(categories[category[i]]);
		}

		return treeModel;
	},
	updateNodes: function(ee) {
		var map = ee.object;
		var scale = map.getScale();

		this.updateNode(this.root, scale);
	},
	updateNode: function(node, scale) {
		var layer = node.attributes;

		if (layer instanceof AWP.Layer.Google) {
		} else if (layer instanceof AWP.Layer.Markers) {
		} else if (layer instanceof AWP.Layer) {
			if (scale) {
				if (layer.minScale < scale || layer.maxScale > scale) {
					node.disable();
					//node.getUI().toggleCheck(false);
				} else {
					node.enable();
				}
			}
			var cs = node.childNodes;
			for (var i = 0, len = cs.length; i < len; i++) {
				this.updateNode(cs[i], scale);
			}
		} else {
			var all_disabled = true, all_enabled = true, cs = node.childNodes;
			for (var i = 0, len = cs.length; i < len; i++) {
				this.updateNode(cs[i], scale);
				if (cs[i].disabled) all_enabled = false;
				if (!cs[i].disabled) all_disabled = false;
			}

			if (cs.length > 0) {
				var icon = node.getUI().getIconEl();
				if (icon) {
					if (all_disabled) {
						icon.src = AWP.cfg.baseURL + 'image/layers-all-disabled.png';
					} else if (all_enabled) {
						icon.src = AWP.cfg.baseURL + 'image/layers-all-enabled.png';
					} else {
						icon.src = AWP.cfg.baseURL + 'image/layers-mixed.png';
					}
				}
			}
		}
	},
	CLASS_NAME: "AWP.Layer.Tree"
});

AWP.Layer.TreeEventModel = Ext.extend(Ext.tree.TreeEventModel, {
	initEvents: function() {
        var el = this.tree.getTreeEl();
        el.on('click', this.delegateClick, this);
		
        if (this.tree.trackMouseOver !== false) {
            el.on('mouseover', this.delegateOver, this);
            el.on('mouseout', this.delegateOut, this);
        }

        //el.on('dblclick', this.delegateDblClick, this);
        el.on('contextmenu', this.delegateContextMenu, this);
    },
    nodeDiv: null,
	delegateOver : function(e, t) {
		if (!this.beforeEvent(e)) {
		    return;
		}
		if (this.lastEcOver) { // prevent hung highlight
		    this.onIconOut(e, this.lastEcOver);
		    delete this.lastEcOver;
		}
		if (e.getTarget('.x-tree-ec-icon', 1)) {
		    this.lastEcOver = this.getNode(e);
		    this.onIconOver(e, this.lastEcOver);
		}
		if (t = this.getNodeTarget(e)) {
			var node = this.getNode(e);
			// mouseover Sub Basin
			var textNode = e.getTarget('.sub-basin', 1);
			if (textNode && node.text.length > 20) {
				//textNode.style.display = 'none';
				
				if (!this.nodeDiv) {
					var div = document.createElement('span');
					document.body.appendChild(div);
					
					div.style.zIndex	= 10000;
					div.style.border	= '1px solid brown';
					div.style.backgroundColor	= 'yellow';
					div.style.position	= 'absolute';
					div.style.padding	= '0px 5px';
					
					this.nodeDiv = div;
					div.onclick = function() {
						this.tree.onSubBasinClick(this.node);
					}
				}
				var div = this.nodeDiv;
				div.style.display	= '';
				
				var pos = ML.getPosition(textNode);
				div.innerHTML		= node.text;
				div.style.left		= pos.x + 'px';
				div.style.top		= pos.y + 'px';
				
				div.tree = this;
				div.node = node;
			} else {
				if (this.nodeDiv) {
					this.nodeDiv.style.display = 'none';
				}
			}
		    this.onNodeOver(e, node);
		}
	},
	delegateOut : function(e, t){
        if (!this.beforeEvent(e)) {
            return;
        }
        if (e.getTarget('.x-tree-ec-icon', 1)) {
            var n = this.getNode(e);
            this.onIconOut(e, n);
            if (n == this.lastEcOver) {
                delete this.lastEcOver;
            }
        }
        if ((t = this.getNodeTarget(e)) && !e.within(t, true)) {
            this.onNodeOut(e, this.getNode(e));
        }
        
		if (this.nodeDiv && e.getTarget() == this.tree.root.ui.wrap) {
			this.nodeDiv.style.display = 'none';
		}
    },
	delegateClick: function(e, t) {
		if (!this.beforeEvent(e)) return;
		
		// 点击 checkbox，子图层用
		if (e.getTarget('input[type=checkbox]', 1)) {
			this.onCheckboxClick(e, this.getNode(e));
		// 点击 buttion，树根节点用
		} else if (e.getTarget('input[type=button]', 1)) {
			this.onNodeClick(e, this.getNode(e));
		// Google 基本层用
		} else if (e.getTarget('input[type=radio]', 1)) {
			this.onRadioClick(e, this.getNode(e));
		// 点击用户数据分类树的节点时触发
		} else if (e.getTarget('.user-feature', 1)) {
			AWP.userContent.onClickFrontTreeNode(this.getNode(e));
		// 点击图标
		} else if (e.getTarget('.x-tree-ec-icon', 1)) {
			this.onIconClick(e, this.getNode(e));
		// 点击属性图标
		} else if (e.getTarget('.x-tree-node-attributes', 1)) {
			var node = this.getNode(e);
			if (node.attributes.category == 'customer') {// 编辑用户数据
				AWP.userContent.onClickFrontEditContent(node);
			} else {
				node.ui.onAttributesClick(e);
			}
		// 点击删除图标
		} else if (e.getTarget('.x-tree-node-delete', 1)) {
			var node = this.getNode(e);
			AWP.userContent.onClickFrontDeleteContent(node.attributes.content_id);
		
		// 点击 Sub Basin
		} else if (e.getTarget('.sub-basin', 1)) {
			this.onSubBasinClick(this.getNode(e));
		
		// 点击节点文本
		} else if (this.getNodeTarget(e)) {
			var node = this.getNode(e);
			if (node.attributes.radio) {
				node.ui.toggleCheck(true);
				/**
				 * seems this is not necessary
				 */
				//this.onRadioClick(e, node);
			} else {
				node.ui.toggleCheck();
				/**
				 * seems this is not necessary
				 */
				//this.onCheckboxClick(e, node);
			}
		}
    },
    onRadioClick: function(e, node) {
        if (!node.ui.onRadioChange) {
            OpenLayers.Console.error("Invalid TreeNodeUI Class, no " +
                                     "onRadioChange is available");
            return;
        }
        node.ui.onRadioChange(e);
    },
    onLayerSelect: function(e, node) {
        //alert('x')
    },
    onSubBasinClick: function(node) {
		var a	= node.attributes;
		// 点击的是 Sub-Basin Polygons
		if (a.gid, a.tbname || a.layerId) {
			var tree	= node.getOwnerTree(),
				gid		= !a.gid || a.gid == tree.gidInfo.gid ? 0 : a.gid;
			AWP.zoomToRegion(gid, a.tbname || a.layerId);
			tree.gidInfo.gid = gid;
		// 点击的是 Show/Hide All
		} else {
			node.ui.toggleCheck();
		}
    }
});

