/*
 * Google Earth API for Ext JS
 * Copyright(c) 2008, Bjorn Sandvik
 * bjorn@thematicmapping.org
 *
 * License: GNU General Public License v3
 * http://extjs.com/license
 *
 * Version: 1.0
 *
 */

Ext.namespace('Ext.ux');

/**
 *
 * @class GEarthPanel
 * @extends Ext.Panel
 */
Ext.ux.GEarthPanel = Ext.extend(Ext.Panel, {

    initComponent: function(){
        var defConfig = {
            border: true,
            kmlTreePanel: new Ext.tree.TreePanel({
        		border: false,
                bodyStyle: 'padding-bottom: 15px',
        		root: new Ext.tree.TreeNode({
        			text: 'KML Documents',
        			iconCls: 'folder',
        			expanded: true
        		}),
                rootVisible: false,
                listeners: {checkchange: {fn: function(node, checked){
            	    node.attributes.kml.setVisibility(checked);
    				node.bubble(function(n){  // If a child node is checked, check all the ancestors
    					if (node.getUI().isChecked()) {
    			        	if (!node.parentNode.getUI().isChecked()) {
    			            	node.parentNode.getUI().toggleCheck();
    			            }
    			        }
    			    })
                }}}
        	}),
        	kmlUrlField: new Ext.form.TextField({
            	fieldLabel: 'URL',
            	width: 195,
            	name: 'url'
        	}),
            earthLayers: {
                LAYER_BORDERS:   true,
                LAYER_ROADS:     false,
                LAYER_BUILDINGS: false,
                LAYER_TERRAIN:   true
            },
            earthOptions: {
                setStatusBarVisibility:    false,
                setGridVisibility:         false,
                setOverviewMapVisibility:  false,
                setScaleLegendVisibility:  false,
                setAtmosphereVisibility:   true,
                setMouseNavigationEnabled: true
            }
        };
        Ext.applyIf(this, defConfig);
        Ext.ux.GEarthPanel.superclass.initComponent.call(this);
        this.addEvents('earthLoaded');
    },

    afterRender: function(){
        Ext.ux.GEarthPanel.superclass.afterRender.call(this);
        google.earth.createInstance(this.body.dom, this.onEarthReady.createDelegate(this), {});
    },

    // Called by above function
    onEarthReady: function(object){
        this.earth = object;
        this.earth.getWindow().setVisibility(true);
        this.earth.getNavigationControl().setVisibility(this.earth.VISIBILITY_SHOW);
        this.addLayers(this.earthLayers);
        this.addOptions(this.earthOptions);
        this.fireEvent('earthLoaded', this);
    },

    getEarth: function(){
        return this.earth;
    },


    addKmlRadio: function(kmlStore){
        var uniqueId = Ext.id();

        // 'None' option
    	var items = [{
           	boxLabel: 'None',
            inputValue: 'none',
            checked: true,
            name: uniqueId
   		}];

    	// Loop through all items in kmlStore
    	for (var count = 0; count < kmlStore.getCount(); count++) {
    	    var item = kmlStore.data.items[count];
  			items.push({
                boxLabel: item.data.name,
                inputValue: item.id,
                name: uniqueId,
                kml: null,
                kmlStore: item.data,
                kmlUrl: item.data.kmlUrl,
                earth: this.earth,
                handler: this.clickHandler
    		});
    	}

        var kmlGroup = new Ext.form.RadioGroup({
    		hideLabel: true,
    		columns: 1,
    		items: items
        });

        return kmlGroup;
    },


    addKmlCheckbox: function(kmlStore){
        var items = [];

    	// Loop through all items in kmlStore
    	for (var count = 0; count < kmlStore.getCount(); count++) {
    	    var item = kmlStore.data.items[count];
  			items.push({
                boxLabel: item.data.name,
                inputValue: item.id,
                kml: null,
                kmlStore: item.data,
                kmlUrl: item.data.kmlUrl,
                earth: this.earth,
                handler: this.clickHandler
    		});
    	}

        var kmlGroup = new Ext.form.CheckboxGroup({
    		hideLabel: true,
    		columns: 1,
    		items: items
        });

        return kmlGroup;
    },


    // Handler used by addKmlRadio and addKmlCheckbox
    clickHandler: function(item, visibility){
        if (item.kml) {
    	    item.kml.setVisibility(visibility); // Toggle KML
    	} else { // Load KML
    	    google.earth.fetchKml(item.earth, item.kmlUrl, function(kmlObject) {
    	        if (kmlObject) {
                    item.earth.getFeatures().appendChild(kmlObject);
                    kmlObject.setVisibility(true)
                }
                else {
                    alert('Bad KML');
                }
    			item.kml = kmlObject;
    		})
        }

        var desc;
		if (visibility) { // Show KML info in south panel
		    var store = item.kmlStore;
		    desc = "<h2>" + store.name + "</h2>"
			     + (store.description != null ? store.description + "<br />" : "")
				 + "Data source: <a href='" + store.sourceUrl + "'>" + store.source + "</a>"
			     + (store.credit != null ? " - Credit: " + store.credit : "")
				 + "<br />KML/KMZ: <a href='" + store.kmlUrl + "'>" + store.kmlUrl + "</a>";
		}
        Ext.getCmp('sourcePanel').body.update(desc);
    },


    fetchKml: function(kmlUrl){
		google.earth.fetchKml(this.earth, kmlUrl, this.addKml.createDelegate(this));
    },

    addKml: function(kmlObject){
        if (kmlObject) {
       		this.earth.getFeatures().appendChild(kmlObject);
       		this.kmlTreePanel.getRootNode().appendChild(this.treeNodeFromKml(kmlObject));
   		} else {
       		alert('Bad KML');
   		}
    },

    treeNodeFromKml: function(kmlObject){
        var result = this.createKmlTreeNode(kmlObject);

    	if(kmlObject.getFeatures().hasChildNodes()) {
    		var subNodes = kmlObject.getFeatures().getChildNodes();
    		for(var i = 0; i < subNodes.getLength(); i++) {
          		var subNode = subNodes.item(i);
          		switch(subNode.getType()) {
        			case 'KmlFolder' :
              			var node = this.treeNodeFromKml(subNode);
        				break;
          			default:
    					var node = this.createKmlTreeNode(subNode);
          				break;
          		}
          		result.appendChild(node);
          	}
        }
    	return result;
    },

    createKmlTreeNode: function(kmlEl){
    	var node = new Ext.tree.TreeNode({
    		text: kmlEl.getName(),
    		checked: (kmlEl.getType() != 'KmlPlacemark' ? (kmlEl.getVisibility() ? true : false) : null),
    		expanded: (kmlEl.getOpen() ? true : false),
    		iconCls: kmlEl.getType(),
    		kml: kmlEl
    	});
    	return node;
    },

    getKmlTreePanel: function(){
        return this.kmlTreePanel;
    },

    getKmlUrlForm: function(){
    	var form = new Ext.FormPanel({
        	frame: false,
            labelWidth: 30,
            border: false,
        	items: this.kmlUrlField,
        	buttons: [{
                text: 'Add KML/KMZ',
                earthPanel: this, // Accessible in handler
                handler: function(button, pressed){
                    // It's all about scope...
                    google.earth.fetchKml(button.earthPanel.earth, button.earthPanel.kmlUrlField.getValue(), button.earthPanel.addKml.createDelegate(button.earthPanel));
                    button.earthPanel.kmlUrlField.reset();
    			}
            }]
    	});
    	return form;
    },

    addLayers: function(layers){
        for (layer in layers){
            this.earth.getLayerRoot().enableLayerById(this.earth[layer], layers[layer]);
        }
    },

    // Returns CheckBoxGroup containing Google Earth layers
    getLayers: function(){
        var layers = this.earthLayers;

        var layerNames = {
            LAYER_BORDERS: 'Borders and names',
            LAYER_ROADS: 'Roads',
            LAYER_BUILDINGS: 'Buildings',
            LAYER_TERRAIN: 'Terrain'
        }

        var items = [];
        for (layer in layers){
  			items.push({
                boxLabel: layerNames[layer],
	            checked: layers[layer],
	            name: layer,
	            earth: this.earth,
    	        handler: function(checkbox, visibility) {
                    checkbox.earth.getLayerRoot().enableLayerById(checkbox.earth[checkbox.name], visibility);
    	        }
    		});
        }
        var layerGroup = new Ext.form.CheckboxGroup({
    		columns: 1,
    		items: items
        });
        return layerGroup;
    },

    addOptions: function(options){
        for (option in options){
            this.earth.getOptions()[option](options[option]);
        }
    },

    // Returns CheckBoxGroup containing Google Earth options
    getOptions: function(){
        var options = this.earthOptions;

        var optionNames = {
            setStatusBarVisibility: 'Show status bar',
            setGridVisibility: 'Show grid',
            setOverviewMapVisibility: 'Show overview map',
            setScaleLegendVisibility: 'Show scale legend',
            setAtmosphereVisibility: 'Show atmosphere',
            setMouseNavigationEnabled: 'Show mouse navigation'
        }

        var items = [];
        for (option in options){
  			items.push({
                boxLabel: optionNames[option],
	            hideLabel: true,
	            checked: options[option],
	            name: option,
	            earth: this.earth,
    	        handler: function(checkbox, visibility) {
                    checkbox.earth.getOptions()[checkbox.name](visibility);
    	        }
    		});
        }
        var optionGroup = new Ext.form.CheckboxGroup({
    		columns: 1,
    		items: items
        });
        return optionGroup;
    }
});

Ext.reg('gearthpanel', Ext.ux.GEarthPanel);
