/**
 * Copyright (c) 2008 The Open Planning Project
 */

Ext.namespace("GeoExt.component");
GeoExt.component.LayerTree = Ext.extend(Ext.tree.TreePanel, {
    
    /**
     * APIProperty: map
     * {OpenLayers.Map}
     */
    map: null,
    
    // deprecated, use this instead
    tree: null,
    
    expanded: true,
    
    // deprecated, use inline options instead
    treeConfig: {},
    
    // deprecated, use inline options instead
    defaultConfig: {},

    groupList: {},

    
    selModel: null,
    autoScroll: true,
    animate: false,
    enableDD: true,
    containerScroll: true,

layerLegend: 'x-tree-node-legend-icon',

    
    initComponent: function() {
        // for backwards compatibility
        Ext.apply(this, this.treeConfig, this.defaultConfig);

        if(!this.root) {
            this.root = new Ext.tree.TreeNode({
                text: "Layers",
                singleClickExpand: true,
                expandable: true,
                expanded: this.expanded,
                draggable: false
            });
        }

        this.selModel = new Ext.tree.MultiSelectionModel();

        GeoExt.component.LayerTree.superclass.initComponent.call(this);
        
        // for backwards compatibility
        this.tree = this;
        if(this.treeConfig && this.treeConfig.listeners) {
            this.on(this.treeConfig.listeners);
        }

        if(this.map) {
            this.setMap(this.map);
        }

    },
    
    onDestroy: function() {
        GeoExt.component.LayerTree.superclass.onDestroy.call(this);
        delete this.tree;
        delete this.map;
    },
    
    setMap: function(map) {
        this.map = map;
        this.map.events.register("addlayer", this, this.redraw);
        this.map.events.register("changelayer", this, this.redraw);
        this.map.events.register("removelayer", this, this.redraw);
        this.redraw();
    },
    
    handleLayerChecked: function(node, visible, layer) {
console.log("LayerTree::handleLayerChecked:  isBaseLayer="+layer.isBaseLayer);
 	if(layer.isBaseLayer) {
	        for(var i=0; i<this.map.layers.length; ++i) {
			var cur = this.map.layers[i];
			//console.log("LayerTree::handleLayerChecked:  layer="+cur.name);
			if(cur.isBaseLayer) {
				cur.setVisibility(false);
			}
        	}
	//JTS - adding this to try to fix the LayerTree not supporting 'multiple base maps' 
          var oldBase = this.map.baseLayer;
                //oldBase.isBaseLayer = false;
                this.map.setLayerZIndex(oldBase, this.map.getLayerIndex(oldBase));
                this.map.baseLayer = null;
                this.map.setBaseLayer(layer);
	//-----------------------------------
	// TODO:
	//  It's working now, just have to figure out how to keep it 'checked'
	//	should also probably not allow re-ordering of base maps...
	}
        layer.setVisibility(visible);
	
	//console.log("LayerTree::handleLayerChecked:  layer="+layer.name);
	loadTControls();
    },

    getBaseIndex: function() {
        // lowest non-hidden layer is considered the base layer
        var base = 0;
        for(var i=0; i<this.map.layers.length; ++i) {
		console.log("getBaseIndex:  "+this.map.layers[i].name);
            if(this.map.layers[i].displayInLayerSwitcher) {
                base = i;
                break;
            }
        }
        return base;
    },
    
    handleLayerMove: function(tree, node, oldParent, newParent, index) {
        // this looks like an Ext bug - variable arguments length
console.log("handleLayerMove");
        var layer = arguments[arguments.length -1];
        var baseIdx = this.getBaseIndex();
        // tree index is highest to lowest in layers array
        var layerIndex = (this.map.layers.length - 1) - index;
        if(layerIndex != this.map.getLayerIndex(layer)) {
            layer.isBaseLayer = (layerIndex == baseIdx);
            this.map.setLayerIndex(layer, layerIndex);
            // two moves we care about
            // 1) moving the old base layer
            // 2) moving a new layer into base position
            if(this.map.baseLayer == layer && layerIndex != baseIdx) {
                var newBase = this.map.layers[baseIdx];
                newBase.isBaseLayer = true;
                this.map.setLayerZIndex(newBase, baseIdx);
                this.map.baseLayer = null;
                this.map.setBaseLayer(newBase);
            } else if(layerIndex == baseIdx) {
                // TODO: when #1195 is fixed
                var oldBase = this.map.baseLayer;
                oldBase.isBaseLayer = false;
                this.map.setLayerZIndex(oldBase, this.map.getLayerIndex(oldBase));
                this.map.baseLayer = null;
                this.map.setBaseLayer(layer);
            }
            this.redraw();
        }
    },
    
    removeSelected: function() {
console.log("remoteSelected");
        var removed = false;
        var nodes = this.getSelectedNodes();
        var node;
        var layers = [];
        Ext.each(nodes, function(node) {
            if(node && node.parentNode) {
                layers.push(this.getLayerFromNode(node));
            }
        }, this);
        var base = false;

        Ext.each(layers, function(layer) {
            base = base || layer.isBaseLayer;
            layer.destroy(false);
        });
        if(base) {
            // TODO: remove this when fixed in trunk
            var baseIdx = this.getBaseIndex();
            this.map.baseLayer = null;
            if(this.map.layers.length > baseIdx) {
                var newBase = this.map.layers[baseIdx];
                newBase.isBaseLayer = true;
                this.map.setBaseLayer(newBase);
            }
        }
        return layers.length;
    },
    
    getSelectedNodes: function() {
        return this.getSelectionModel().getSelectedNodes();
    },

    getLayerFromNode: function(node) {
        var layer = null;
        var index = this.root.indexOf(node);
        if(index >= 0) {
            var layerIndex = this.map.layers.length - 1 - index;
            layer = this.map.layers[layerIndex];
        }
        return layer;
    },

    draw : function ()
    {
    alert('draw');
    },

    redraw: function() {
        var layer;
        var expanded = this.root.expanded;
	
        while(this.root.firstChild) {
            this.root.removeChild(this.root.firstChild);
        }

/***********************/
	this.groupList = [];
	var group = '';
	//for(var i=this.map.layers.length-1; i>=0; --i) {
	//for(var i=this.layers.length-1; i>=0; --i) {
	for(var i=0;i<this.map.layers.length;i++) {
        	layer = this.map.layers[i];
		if(this.groupList.indexOf(layer.options.GROUP) == -1) {
			//alert('Adding group: '+layer.options.GROUP);
			this.groupList.push(layer.options.GROUP);

this.parent = new Ext.tree.TreeNode({
		id: layer.options.GROUP,
                text: layer.options.GROUP,
                singleClickExpand: true,
                expandable: true,
                expanded: this.expanded,
                draggable: true
            });
	this.root.appendChild(this.parent);


		}
	}
/***********************/

        //for(var i=this.map.layers.length-1; i>=0; --i) {
	for(var i=0;i<this.map.layers.length;i++) {
            layer = this.map.layers[i];
//console.debug("LayerTree::redraw:  layer="+layer.name);
            if(layer.displayInLayerSwitcher) {
                var node = new Ext.tree.TreeNode({
                    text: layer.name,
                    draggable: true,
                    checked: layer.visibility,
                    allowDrop: false,
		    allowChildren: true,
                    leaf: false
                });
                node.on({
                    "checkchange": this.handleLayerChecked.createDelegate(
                        this, [layer], true
                    ),
                    "dblclick": function(node, evt) {
                        // this appears to be a bug in Ext
                        node.ui.toggleCheck(!node.ui.isChecked()); 
                    },
                    "move": {
                        fn: this.handleLayerMove.createDelegate(
                           this, [layer], true
                       ),
                       delay: 100
                   }
               });

		if (layer.options.legend) {
                	var legendNode = new Ext.tree.TreeNode({
	                    dragable: false,
        	            allowChildren: false,
        	            iconCls: this.layerLegend,
        	            icon: layer.options.legend
        	      });
        	        node.appendChild(legendNode);
            	}

		var pNode = this.tree.getNodeById(layer.options.GROUP);

		if(pNode)
			pNode.appendChild(node);
		else
	                this.root.appendChild(node);

            }
        }
        if(expanded) {
            this.root.expand();
        }
    },

    CLASS_NAME: "GeoExt.component.LayerTree"
});
Ext.reg("layertree", GeoExt.component.LayerTree);

