/*
 * Ext JS Library 2.2.1
 * Copyright(c) 2006-2009, Ext JS, LLC.
 * licensing@extjs.com
 * 
 * http://extjs.com/license
 */

/**
 * @class Ext.ux.XmlTreeLoader
 * @extends Ext.tree.TreeLoader
 * <p>A TreeLoader that can convert an XML document into a hierarchy of {@link Ext.tree.TreeNode}s.
 * Any text value included as a text node in the XML will be added to the parent node as an attribute
 * called <tt>innerText</tt>.  Also, the tag name of each XML node will be added to the tree node as
 * an attribute called <tt>tagName</tt>.</p>
 * <p>By default, this class expects that your source XML will provide the necessary attributes on each 
 * node as expected by the {@link Ext.tree.TreePanel} to display and load properly.  However, you can
 * provide your own custom processing of node attributes by overriding the {@link #processNode} method
 * and modifying the attributes as needed before they are used to create the associated TreeNode.</p>
 * @constructor
 * Creates a new XmlTreeloader.
 * @param {Object} config A config object containing config properties.
 */
function groupClick(node, event) {
	if (node.expanded)
		node.collapse();
	else
		node.expand();
}
function folderClick(node, event) {
	if (node.expanded)
		node.collapse();
	else
		node.expand();
}
function serviceClick(node, event) {
	if (event.target.id=='hrefAyuda') {
		node.hrefClicked=true;
	} else event.stopEvent();
}
function countActiveLayers(node) {
	if (node.parentNode.attributes.tagName=='service')
		var parent = node.parentNode; // service
	else
		var parent = node.parentNode.parentNode;
	var count = 0;
	parent.eachChild(function(child){
		if (child.attributes.tagName=='folder') {
			child.eachChild(function(child){
				if (child.isSelectedByConfigure()) count++;
			});
		} else if (child.isSelectedByConfigure()) count++;
	});
	return count;
}
function layerClick(node, event) {
	// nodo padre servicio
	if (node.parentNode.attributes.tagName=='service')
		var parentService = node.parentNode;
	else if (node.parentNode.attributes.tagName=='folder')
		var parentService = node.parentNode.parentNode;
	
	// si no es capa del servicio activo, salimos
	if (parentService.attributes.name!=grafcan.curService) return false;
	
	// capa fija
	if (node.attributes.fixed && eval(node.attributes.fixed)) return false;
	
	// ha de haber, al menos, una capa activa
	var visible = !node.isSelectedByConfigure();
	if (countActiveLayers(node)==1 && !visible) return false;

	// si sólo puede haber una capa fixed a la vez (onlyOneFixedLayer), configurarlo de tal forma
	if (parentService.attributes.onlyOneFixedLayer && eval(parentService.attributes.onlyOneFixedLayer)) {
		var layers = parentService.getRecursiveChild();
		Ext.each(layers, function(item, index, allItems){
			if (item.attributes.fixed && eval(item.attributes.fixed)) return;
			if (item.isSelectedByConfigure()) {
				grafcan.changeLayerState(parentService.attributes.name, item.attributes.desc, false);
				item.configureSelect(false);
			}
		});
	}
	grafcan.changeLayerState(grafcan.curService, node.attributes.desc, visible);
	node.configureSelect(visible);
}
Ext.ux.XmlTreeLoader = Ext.extend(Ext.tree.TreeLoader, {
    /**
     * @property  XML_NODE_ELEMENT
     * XML element node (value 1, read-only)
     * @type Number
     */
    XML_NODE_ELEMENT : 1,
    /**
     * @property  XML_NODE_TEXT
     * XML text node (value 3, read-only)
     * @type Number
     */
    XML_NODE_TEXT : 3,
	
	requestMethod: 'GET', // forzamos la llamada GET
	
    // private override
    processResponse : function(response, node, callback){
        var xmlData = response.responseXML;
        var root = xmlData.documentElement || xmlData;

        try{
            node.beginUpdate();
			if (!node.isRoot) {
				if (node.attributes.tagName!='folder') {
					if ($ie())
						var subRoot = root.selectSingleNode("//"+node.attributes.tagName+"[@name='"+node.attributes.name+"']");
					else
						var subRoot = root.ownerDocument.evaluate("//"+node.attributes.tagName+"[@name='"+node.attributes.name+"']", root, null, XPathResult.ANY_TYPE, null).iterateNext();
					node.appendChild(this.parseXml(subRoot, node));
				} else {
					if ($ie())
						var subRoot = root.selectSingleNode("//service[@name='"+node.attributes.service+"']/layers");
					else
						var subRoot = root.ownerDocument.evaluate("//service[@name='"+node.attributes.service+"']/layers", root, null, XPathResult.ANY_TYPE, null).iterateNext();
					node.appendChild(this.parseXml(subRoot, node, node.attributes.folderName));
				}
			} else
				node.appendChild(this.parseXml(root));
            node.endUpdate();
            
            if(typeof callback == "function"){
                callback(this, node);
            }
        }catch(e){
            this.handleFailure(response);
        }
    },
    
    // private
    parseXml : function(node, treeNodeParent, fldName) {
        var nodes = [];
        Ext.each(node.childNodes, function(n){
			if(n.nodeType == this.XML_NODE_ELEMENT) {
				var treeNode = this.createNode(n);
				switch(n.tagName) {
					case 'group':
						if (n.childNodes.length > 0) {
							var child = this.parseXml(n, treeNode);
							treeNode.appendChild(child);
						}
						treeNode.on('click', groupClick);
						nodes.push(treeNode);
						break;
					case 'service':
						if (n.attributes.getNamedItem('forBrowse') && n.attributes.getNamedItem('forBrowse').value=='false') 
							break;
						if ($ie())
							var href = n.selectSingleNode('href');
						else
							var href = n.ownerDocument.evaluate('href', n, null, XPathResult.ANY_TYPE, null).iterateNext();
						if (href) {
							var url = href.text||href.textContent;
							var title = (href.attributes.getNamedItem('title')?href.attributes.getNamedItem('title').value:'');
							treeNode.attributes.href = url;
							treeNode.attributes.hrefTarget = '_blank';
							treeNode.text = treeNode.text+'&nbsp;&nbsp;<a id="hrefAyuda" href="'+url+'" target="_blank" onclick="return true" title="'+title+'" style="color:#0000ff;font-size:9px;text-decoration:underline">'+_('Ayuda')+'</a>';
						}
						if (n.childNodes.length > 0) {
							var child = this.parseXml(n, treeNode);
							treeNode.appendChild(child);
						}
						treeNode.on('click', serviceClick);
						nodes.push(treeNode);
						break;
					case 'layers':
						if (n.childNodes.length > 0) {
							var parentSelected = false;
							if (grafcan.extLoaded) {
								if (treeNodeParent.isSelectedByConfigure())
									parentSelected = true;
								else
									parentSelected = false;
							}
							if ($ie()) {
								var folderLayers = n.selectNodes("layer[@folder]");
								if (folderLayers.length>0) { // creamos las carpetas, si existen
									for (var i=0;i<folderLayers.length;i++) {
										var folderName = folderLayers[i].attributes.getNamedItem('folder').value;
										var folderNode = treeNodeParent.findChild('folderName', folderName);
										if (!folderNode) {
											folderNode = this.createNode({tagName:'folder',attributes:[{nodeName:'folderName',nodeValue:folderName},{nodeName:'service',nodeValue:treeNodeParent.attributes.name}]});
											folderNode.on('click', folderClick);
											folderNode.disabled = !parentSelected;
											treeNodeParent.appendChild(folderNode); // añadimos la carpeta como hija del servicio
										}
									}
								}
							} else {
								var folderLayers = n.ownerDocument.evaluate("layer[@folder]", n, null, XPathResult.ANY_TYPE, null);
								var folder = folderLayers.iterateNext();
								while (folder) {
									var folderName = folder.attributes.getNamedItem('folder').value;
									var folderNode = treeNodeParent.findChild('folderName', folderName);
									if (!folderNode) {
										folderNode = this.createNode({tagName:'folder',attributes:[{nodeName:'folderName',nodeValue:folderName},{nodeName:'service',nodeValue:treeNodeParent.attributes.name}]});	
										folderNode.on('click', folderClick);
										folderNode.disabled = !parentSelected;
										treeNodeParent.appendChild(folderNode); // añadimos la carpeta como hija del servicio
									}
									folder = folderLayers.iterateNext();
								}
							}
							var child = this.parseXml(n, treeNodeParent);
							treeNodeParent.appendChild(child); // sólo añade como hijos las capas sin carpeta
						}
						break;
					case 'layer':
						if (treeNode.attributes.name!='ghost') {
							treeNode.on('click', layerClick);
							if (fldName) { // sólo las capas de una carpeta específica
								if (n.attributes.getNamedItem('folder') && n.attributes.getNamedItem('folder').value==fldName) {
									if (grafcan.extLoaded) {
										if (treeNodeParent.parentNode.isSelectedByConfigure()) // si el servicio es el activo: service-->folder-->layer(s)
											//treeNode.enable();
											treeNode.disabled = false;
										else
											//treeNode.disable(); // falla en this.unselect() (sentencia ejecutada en el método disable())
											treeNode.disabled = true;
									}
									nodes.push(treeNode);
								}
							} else {
								var folderNode = null;
								if (n.attributes.getNamedItem('folder')) {
									var folderName = n.attributes.getNamedItem('folder').value;
									var folderNode = treeNodeParent.findChild('folderName', folderName);
									// el nodo carpeta debe existir
									folderNode.appendChild(treeNode);
								}
								if (grafcan.extLoaded) {
									if (treeNodeParent.isSelectedByConfigure()) // si el servicio es el activo: service-->layer(s)
										//treeNode.enable();
										treeNode.disabled = false;
									else
										//treeNode.disable(); // falla en this.unselect() (sentencia ejecutada en el método disable())
										treeNode.disabled = true;
								}
								if (!folderNode) {
									if (nodes.length>0) {
										var _nodes = [treeNode];
										nodes = _nodes.concat(nodes);
									} else
										nodes.push(treeNode);
								}
							}
						}
						break;
				}
				if (treeNode.attributes.name) treeNode.id = treeNode.attributes.name;
			}
        }, this);
        
        return nodes;
    },
    
	// private override
    createNode : function(node){
        var attr = {
            tagName: node.tagName
        };
        
		if (node.attributes && node.attributes.length>0) {
			Ext.each(node.attributes, function(a){
				attr[a.nodeName] = a.nodeValue;
			});
			this.processAttributes(attr);
		}
        
        return Ext.ux.XmlTreeLoader.superclass.createNode.call(this, attr);
    },
    
    /*
     * Template method intended to be overridden by subclasses that need to provide
     * custom attribute processing prior to the creation of each TreeNode.  This method
     * will be passed a config object containing existing TreeNode attribute name/value
     * pairs which can be modified as needed directly (no need to return the object).
     */
    processAttributes: Ext.emptyFn
});


//
// Extend the XmlTreeLoader to set some custom TreeNode attributes specific to our application:
//
Ext.app.ServiceLoader = Ext.extend(Ext.ux.XmlTreeLoader, {
	processAttributes : function(attr){
		if(attr.tagName=='group'){ // grupo
			
			// Nombre del grupo
			attr.text = _(attr.desc);
			attr.cls = 'treeNode';
			
			// Icono del grupo
			//attr.iconCls = 'author-' + attr.gender;
			
			// Override these values for our folder nodes because we are loading all data at once.  If we were
			// loading each node asynchronously (the default) we would not want to do this:
			attr.loaded = true;
			try{attr.expanded = eval(attr.expand);}catch(e){attr.expanded = false;}
		}
		else if(attr.tagName=='service'){ // servicio
			
			// Nombre del servicio y notificación de novedad
			if (attr.highlight && attr.highlight=='true') {				
				attr.text = _(attr.desc)+'<img src="img/new_'+grafcan.lang+'.gif" border="0" style="margin-left:5px"/>';
				attr.cls = 'Service_new';
			} else {
				attr.text = _(attr.desc);
				attr.cls = 'treeNode';
			}
				
			// href

			// Icono del servicio
			attr.iconCls = 'Service_0';
			
			attr.expanded = (attr['default'] && eval(attr['default']));
		}
		else if(attr.tagName=='folder'){ // carpeta
			
			// Nombre de la capa
			attr.text = _(attr.folderName);
			attr.cls = 'treeNode';
			attr.disabled = true;
			
			// Icono del servicio
			//attr.iconCls = 'book';
			
		}
		else if(attr.tagName=='layer'){ // capa
			
			// Nombre de la capa
			attr.text = _(attr.desc);
			attr.cls = 'treeNode';
			
			// Icono del servicio
			attr.iconCls = eval(attr.visible)?'Layer_1':'Layer_0';
			
			// Tell the tree this is a leaf node.  This could also be passed as an attribute in the original XML,
			// but this example demonstrates that you can control this even when you cannot dictate the format of 
			// the incoming source XML:
			attr.leaf = true;
		}
	}
});

// búsqueda recursiva de nodos
Ext.tree.TreeNode.prototype.findRecursiveChild = function(attrName, attrValue) {
	var node = null;
	this.eachChild(function(child) {
		if (child.attributes.tagName=='folder') {
			node = child.findChild(attrName, attrValue);
			if (node) return false;
		} else {
			if (child.attributes[attrName]==attrValue) {
				node=child;
				return false;
			}
		}
	});
	return node;
}
// array de nodos capa de un servicio
Ext.tree.TreeNode.prototype.getRecursiveChild = function() {
	var nodes = [];
	this.eachChild(function(child) {
		if (child.attributes.tagName=='folder') {
			child.eachChild(function(child) {
				nodes.push(child);
			});
		} else
			nodes.push(child);
	});
	return nodes;
}
Ext.tree.TreeNode.prototype.configureSelect = function(visible) {
/*
 * Configura un nodo como nodo seleccionado
 */ 	
	var itemName = '';
	switch(this.attributes.tagName) {
		case 'service':
			itemName = 'Service';
			this.eachChild(
				function(child){
					child.cascade(function(node){
						if(visible)
							node.enable();
						else
							node.disable();
					});
			});
			break;
		case 'layer':
			itemName = 'Layer';
			break;
		default:
			return false;
			break;
	}
	if (visible) {
		var state0 = '0';
		var state1 = '1';
	} else {
		var state0 = '1';
		var state1 = '0';
	}
	this.attributes.iconCls = itemName+'_'+state1;
	if (this.ui.iconNode)
		this.ui.iconNode.className = this.ui.iconNode.className.replace(itemName+'_'+state0,itemName+'_'+state1);
	grafcan.extLoaded = true;
}
Ext.tree.TreeNode.prototype.isSelectedByConfigure = function() {
	var itemName = '';
	switch(this.attributes.tagName) {
		case 'service':
			itemName = 'Service';
			break;
		case 'layer':
			itemName = 'Layer';
			break;
		default:
			return false;
			break;
	}
	return this.attributes.iconCls == itemName+'_1';
}

/* Ext.form.TextField.setFieldLabel(text) */
Ext.override(Ext.form.TextField, {
	setFieldLabel: function(text) {
		try{Ext.fly(this.el.dom.parentNode.previousSibling).update(text);}catch(ex){}
	}
});
/* Ext.form.TextField.hide: oculta también la label */
Ext.override(Ext.form.TextField, {
	hide: function() {
		try{this.container.up('div.x-form-item').hide();}catch(e){}
	}
});
Ext.override(Ext.form.TextField, {
	show: function() {
		try{this.container.up('div.x-form-item').show();}catch(e){}
	}
});
// Comunicación Flash
function drawPerfilPoint(x,y) {
	if (x && y) {
		//var p = utm2geo(x, y);
		var p = UTMRefToLatLng(x, y, 28, 'R');
		var myIcon = new GIcon(G_DEFAULT_ICON);
		//myIcon.image = 'http://www.google.com/mapfiles/markerA.png';
		myIcon.image = 'http://labs.google.com/ridefinder/images/mm_20_blue.png';
		try{map.removeOverlay(grafcan.perfilMarker);}catch(e){}
		grafcan.perfilMarker = new GMarker(new GLatLng(p.lat, p.lng), {icon:myIcon});
		map.addOverlay(grafcan.perfilMarker);
	} else {
		if (grafcan.perfilMarker) {
			map.removeOverlay(grafcan.perfilMarker);
			grafcan.perfilMarker = null;
		}
	}
}
/*!
 * Ext JS Library 3.0+
 * Copyright(c) 2006-2009 Ext JS, LLC
 * licensing@extjs.com
 * http://www.extjs.com/license
 */
Ext.ns('Ext.ux.form');

/**
 * @class Ext.ux.form.FileUploadField
 * @extends Ext.form.TextField
 * Creates a file upload field.
 * @xtype fileuploadfield
 */
Ext.ux.form.FileUploadField = Ext.extend(Ext.form.TextField,  {
    /**
     * @cfg {String} buttonText The button text to display on the upload button (defaults to
     * 'Browse...').  Note that if you supply a value for {@link #buttonCfg}, the buttonCfg.text
     * value will be used instead if available.
     */
    buttonText: 'Browse...',
    /**
     * @cfg {Boolean} buttonOnly True to display the file upload field as a button with no visible
     * text field (defaults to false).  If true, all inherited TextField members will still be available.
     */
    buttonOnly: false,
    /**
     * @cfg {Number} buttonOffset The number of pixels of space reserved between the button and the text field
     * (defaults to 3).  Note that this only applies if {@link #buttonOnly} = false.
     */
    buttonOffset: 3,
    /**
     * @cfg {Object} buttonCfg A standard {@link Ext.Button} config object.
     */

    // private
    readOnly: true,

    /**
     * @hide
     * @method autoSize
     */
    autoSize: Ext.emptyFn,

    // private
    initComponent: function(){
        Ext.ux.form.FileUploadField.superclass.initComponent.call(this);

        this.addEvents(
            /**
             * @event fileselected
             * Fires when the underlying file input field's value has changed from the user
             * selecting a new file from the system file selection dialog.
             * @param {Ext.ux.form.FileUploadField} this
             * @param {String} value The file value returned by the underlying file input field
             */
            'fileselected'
        );
    },

    // private
    onRender : function(ct, position){
        Ext.ux.form.FileUploadField.superclass.onRender.call(this, ct, position);

        this.wrap = this.el.wrap({cls:'x-form-field-wrap x-form-file-wrap'});
        this.el.addClass('x-form-file-text');
        this.el.dom.removeAttribute('name');

        this.fileInput = this.wrap.createChild({
            id: this.getFileInputId(),
            name: this.name||this.getId(),
            cls: 'x-form-file',
            tag: 'input',
            type: 'file',
            size: 1
        });

        var btnCfg = Ext.applyIf(this.buttonCfg || {}, {
            text: this.buttonText
        });
        this.button = new Ext.Button(Ext.apply(btnCfg, {
            renderTo: this.wrap,
            cls: 'x-form-file-btn' + (btnCfg.iconCls ? ' x-btn-icon' : '')
        }));

        if(this.buttonOnly){
            this.el.hide();
            this.wrap.setWidth(this.button.getEl().getWidth());
        }

        this.fileInput.on('change', function(){
            var v = this.fileInput.dom.value;
            this.setValue(v);
            this.fireEvent('fileselected', this, v);
        }, this);
    },

    // private
    getFileInputId: function(){
        return this.id + '-file';
    },

    // private
    onResize : function(w, h){
        Ext.ux.form.FileUploadField.superclass.onResize.call(this, w, h);

        this.wrap.setWidth(w);

        if(!this.buttonOnly){
            var w = this.wrap.getWidth() - this.button.getEl().getWidth() - this.buttonOffset;
            this.el.setWidth(w);
        }
    },

    // private
    onDestroy: function(){
        Ext.ux.form.FileUploadField.superclass.onDestroy.call(this);
        Ext.destroy(this.fileInput, this.button, this.wrap);
    },


    // private
    preFocus : Ext.emptyFn,

    // private
    getResizeEl : function(){
        return this.wrap;
    },

    // private
    getPositionEl : function(){
        return this.wrap;
    },

    // private
    alignErrorIcon : function(){
        this.errorIcon.alignTo(this.wrap, 'tl-tr', [2, 0]);
    }

});

Ext.reg('fileuploadfield', Ext.ux.form.FileUploadField);

// backwards compat
Ext.form.FileUploadField = Ext.ux.form.FileUploadField;
/*!
 * Ext JS Library 3.0+
 * Copyright(c) 2006-2009 Ext JS, LLC
 * licensing@extjs.com
 * http://www.extjs.com/license
 */
Ext.ns('Ext.ux.grid');

/**
 * @class Ext.ux.grid.CheckColumn
 * @extends Object
 * GridPanel plugin to add a column with check boxes to a grid.
 * <p>Example usage:</p>
 * <pre><code>
// create the column
var checkColumn = new Ext.grid.CheckColumn({
   header: 'Indoor?',
   dataIndex: 'indoor',
   id: 'check',
   width: 55
});

// add the column to the column model
var cm = new Ext.grid.ColumnModel([{
       header: 'Foo',
       ...
    },
    checkColumn
]);

// create the grid
var grid = new Ext.grid.EditorGridPanel({
    ...
    cm: cm,
    plugins: [checkColumn], // include plugin
    ...
});
 * </code></pre>
 * In addition to storing a Boolean value within the record data, this
 * class toggles a css class between <tt>'x-grid3-check-col'</tt> and
 * <tt>'x-grid3-check-col-on'</tt> to alter the background image used for
 * a column.
 */
Ext.ux.grid.CheckColumn = function(config){
    Ext.apply(this, config);
    if(!this.id){
        this.id = Ext.id();
    }
    this.renderer = this.renderer.createDelegate(this);
};

Ext.ux.grid.CheckColumn.prototype = {
    init : function(grid){
        this.grid = grid;
        this.grid.on('render', function(){
            var view = this.grid.getView();
            view.mainBody.on('mousedown', this.onMouseDown, this);
        }, this);
    },

    onMouseDown : function(e, t){
		if (e.button==2) return; // sólo botón izquierdo
        if(t.className && t.className.indexOf('x-grid3-cc-'+this.id) != -1){
            e.stopEvent();
            var index = this.grid.getView().findRowIndex(t);
            var record = this.grid.store.getAt(index);
            record.set(this.dataIndex, !record.data[this.dataIndex]);
        }
    },

    renderer : function(v, p, record){
        p.css += ' x-grid3-check-col-td'; 
        return '<div class="x-grid3-check-col'+(v?'-on':'')+' x-grid3-cc-'+this.id+'">&#160;</div>';
    }
};

// register ptype
Ext.preg('checkcolumn', Ext.ux.grid.CheckColumn);

// backwards compat
Ext.grid.CheckColumn = Ext.ux.grid.CheckColumn;