/*
 * (C) 2006, 2007, 2008 Gabriel Mansi (gabriel.mansi@gmail.com)
 * Ajax component manager
 * Licensed under the terms of the GNU Lesser General Public License:
 * http://www.fsf.org/licensing/licenses/lgpl.html
 *
 */

function GOLDContext( country, language, timeZone ) {
    this.country = country ;
    this.language = language ;
    this.timeZone = timeZone ;
    this.sessionId = null ;
}

/**
 *
 * properties: 
 * { [ elementId | element ], rootNode, handler, 
 */
function GOLDComponent( properties ) {
  
    this.IE_XMLHTTP_AX = new Array( "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP" ) ;
    
    this.parameters = null ;
    this.validator = new Array() ;
    this.debugLayer = null ;
    this.MAX_DEBUG_LINES = 50 ;
    this.currentDebugLines = 0 ;
    this.infoLayer = null ;
    this.componentPath = "../../core/components/" ;
    this.componentFileExtension = ".jsp" ;
    this.async = false ;
    if (properties && properties.rootNode) this.rootNode = properties.rootNode ;
    else this.rootNode = document ;

    this.elementId = null ;
    this.element = null ;

    if (properties && properties.elementId) {
        this.element = this.rootNode.getElementById( properties.elementId ) ;
    } else if (properties && properties.element) {
        this.element = properties.element ;
    }

    if (properties && properties.parent) this.parent = properties.parent ;

    
    this.name = "component" ;
    // Default locale values
    this.context = new GOLDContext( "ar", "es", "America/Buenos_Aires" ) ;
    this.handler = null ;
    if (properties && properties.handler)
        this.handler = properties.handler ;
    // data for persistence
    this.data = new Object() ;
    
    // last url accessed, see reload method
    this.lastURL = null ;
    this.method = "GET" ;
      
}

GOLDComponent.prototype.expandCollapseElement = function( element ) {
    var nextRow = this.getNextElement( element.parentNode ) ;
    var table = this.getFirstChild( this.getFirstChild( nextRow ) ) ;
    var show = this.showHideElement( table ) ;
    var img = this.getFirstChild( this.getFirstChild( element ) ) ;
    var def = "../../images/default/16x16/" ;
    if (show)
      img.src = def + "tree-item-expanded.png" ;
    else
      img.src = def + "tree-item-collapsed.png" ;
}


GOLDComponent.prototype.setElement = function( element ) {
    this.element = element ;
}

GOLDComponent.prototype.setName = function( name ) {
    this.name = name ;
}

GOLDComponent.prototype.setAsync = function( async ) {
    this.async = async ;
}

/**
 * Sets the component path (default ../components/)
 */
GOLDComponent.prototype.setComponentPath = function( path ) {
    this.componentPath = path ;
}

/**
 * Sets the component file extension (.php, .jsp, ...)
 */
GOLDComponent.prototype.setComponentFileExtension = function( ext ) {
    this.componentFileExtension = ext ;
}

GOLDComponent.prototype.setInfoLayer = function( l ) {
    this.infoLayer = document.getElementById( l )  ;
}

GOLDComponent.prototype.showInfo = function( str ) {
    if ( this.infoLayer ) {
        this.setOpacity( this.infoLayer, 0 ) ;
        this.loadComponent( "message", this.infoLayer, { handler: this.handler, message: str, type: "Info" }, null ) ;
        this.infoFadeIn() ;
    }

}

GOLDComponent.prototype.showError = function( str ) {
    if ( this.infoLayer ) {
        this.setOpacity( this.infoLayer, 0 ) ;
        this.loadComponent( "message", this.infoLayer, { handler: this.handler, message: str, type: "Error" }, null ) ;
        this.infoFadeIn() ;
    }
}

GOLDComponent.prototype.showTemporalInfo = function( str ) {
    if ( this.infoLayer ) {
        /* FIXME: some browsers don't handle blink */
        this.infoLayer.innerHTML = '<span class="goldBlinkingText">' + str + '</span>' ;
    }
}

GOLDComponent.prototype.clearError = function( ) {
    this.infoLayer.innerHTML = "" ;
}

GOLDComponent.prototype.debug = function( str ) {
    if ( this.debugLayer != null ) {
        if ( ++this.currentDebugLines > this.MAX_DEBUG_LINES ) {
            this.debugLayer.innerHTML = "" ;
            this.currentDebugLines = 0 ;
        }
        this.debugLayer.innerHTML += str + "<br>" ;
    }
}

GOLDComponent.prototype.clearDebug = function( ) {
if ( this.debugLayer != null )
    this.debugLayer.innerHTML = "" ;
}

GOLDComponent.prototype.setDebugLayer = function( l ) {
this.debugLayer = document.getElementById( l )  ;
}

GOLDComponent.prototype.setParameters = function( p ) {
this.parameters = p ;
}

GOLDComponent.prototype.addValidator = function( v ) {
this.validators[ this.validators.length ] = v ;
}


GOLDComponent.prototype.callRPC = function( method, obj ) {
	var url = "../../xmlrpc" ;
	var xmlrpc = importModule( "xmlrpc" ) ;
	var service = new xmlrpc.ServiceProxy( url, [ this.name + "." + method ] );
	var cookie = document.cookie ;
	if (cookie) {
	    var cookies = cookie.split( ";" ) ;
	    if (cookies) {
	        for (var i = 0 ; i < cookies.length ; i++) {
	            var map = cookies[ i ].split( "=" ) ;
	            if (map[ 0 ] == "JSESSIONID" ) {
	                this.context.sessionId = map[ 1 ] ;
	                break ;
	            }
	        }
	    }
	}
	var ret = null ;
	eval( "ret = service." + this.name + "." + method  + "( this.context, obj ) ;" ) ;
	return ret ;
}

/**
* Invokes a remote method with the form f.
*/
GOLDComponent.prototype.callFromForm = function( method, f ) {
	var obj = this.formToObject( f ) ;
	return this.rpcCall( method, obj ) ;

}

GOLDComponent.prototype.loadURL = function( url ) {
    var req = this.loadHttpRequest( url ) ;
    if (this.async) {
        req.onreadystatechange = function() {
            if ( req.readyState == 4 ) {
                this.element.innerHTML = new String( req.responseText ) ;
            }
        }
    } else {
        this.element.innerHTML = new String( req.responseText ) ;
    }	
    
    return req ;
    
}
 
/**
 * provides basic http request handling
 */
GOLDComponent.prototype.loadHttpRequest = function( url ) {
    var req ;
    this.lastURL = url ;
    
    if ( window.XMLHttpRequest ) {
        req = new XMLHttpRequest( ) ;
    } else {
        if ( window.ActiveXObject ){ // IE
            for ( var i = 0 ; i < this.IE_XMLHTTP_AX.length ; i++ ) {
                try {
                    req = new ActiveXObject( this.IE_XMLHTTP_AX[ i ] ) ;
                    break ;
                } catch ( e ) { }
            }
        }
    }
    if ( req ) {
        if ( this.method == "GET" ) {
            req.open( 'GET', url, this.async ) ;
            req.send( null ) ;
        } else {
            var data = url.split( "?" ) ;
            var page = data[ 0 ] ;
            var params = null ;
            if ( data.length > 1 )
                params = data[ 1 ] ;
            
            req.open( "POST", page, this.async );
            req.setRequestHeader( "Content-type", "application/x-www-form-urlencoded" ) ;
            req.setRequestHeader( "Content-length", params == null ? "0" : params.length ) ;
            req.setRequestHeader( "Connection", "close") ;
            req.send( params ) ;            
        }
    }
    return req ;
}

/**
* Loads a html component
*/
GOLDComponent.prototype.loadRequest = function( componentName, params, options ) {
	
	var parametros = "" ;
		
	if ( params ) {
	    parametros += "?" ;
	    for ( var i in params )	{
	        parametros += i + "=" + escape( params[ i ] ) + "&" ;
	    }
	}
	return this.loadHttpRequest( this.componentPath + componentName + this.componentFileExtension + parametros ) ;
}

GOLDComponent.prototype.reload = function() {
	if (this.lastURL) {
		this.loadURL( this.lastURL ) ;
	}
}

GOLDComponent.prototype.load = function( params, options ) {
	this.loadComponent( this.name, this.element, params, options ) ;
}

/**
* Loads a html component
*/
GOLDComponent.prototype.loadComponent = function( componentName, element, params, options ) {
	var req = this.loadRequest( componentName, params, options ) ;
	if (this.async) {
	    req.onreadystatechange = function() {
	        if ( req.readyState == 4 ) {
	            element.innerHTML = new String( req.responseText ) ;
	        }
	    }
	} else {
    	    element.innerHTML = req.responseText ;
	}	
	
}

/**
* Loads and executes javascript code
*/
GOLDComponent.prototype.executeJavascript = function( componentName, params, options ) {
	var req = this.loadRequest( componentName, params, options ) ;
        if (this.async) {
          req.onreadystatechange = function() {
              if ( req.readyState == 4 ) {
                  eval( req.responseText ) ;
              }
          }
        } else {
            eval( req.responseText ) ;
        }
}

function GOLDAlertError( str, element ) {
    alert( str ) ;
    if ( element ) element.focus() ;
    return false ;
}

function GOLDValidationResult( element, isValid, message ) {
    this.element = element ;
    this.isValid = isValid ;
    this.message = message ;
}

function GOLDStringTrim( str ) {
  var aux = str ;
  for ( i = 0 ; i < aux.length ; i++ )
          if ( aux.charAt( i ) != ' ' ) break ;

  aux = aux.substring( i ) ;

  if ( aux.length > 1 ) {
      for ( i = aux.length ; i > 0 ; i-- )
          if ( aux.charAt( i - 1 ) != ' ' ) break ;
      aux = aux.substring( 0, i ) ;
  }
  return aux ;
}

function GOLDValidationGroup( ) {
    this.itemList = new Array();
}

GOLDValidationGroup.prototype.addItem = function( item ) {
    this.itemList[ this.itemList.length++ ] = item ;
}


/**
 * returns an array of validation result
 */
GOLDComponent.prototype.formValidate = function( f ) {
    var ret = new Array() ;
    var e = f.elements ;
    
    for ( var i = 0 ; i < e.length ; i++ ) {
        var props = e[ i ].getAttribute( "gp" ) ;
        if ( props != null && props != "" ) {
          var gp = null ;
          eval( "gp = " + props + " ;" ) ;
          
          var value = null ; 
          if ( e[ i ].value != undefined ) {
            value = e[ i ].value ;
            if ( gp.type && ( gp.required || value != "" ) ) {
                var re = null ;
                var message = null ;
                if ( gp.type == "date" ) {
                    re = /^\d{1,2}\/\d{1,2}\/\d{4}$/;
                    message = "Formato de fecha no válido, el dato ingresado debe tener el formato dd/mm/aaaa, por ej. 29/04/2007" ;
                } else if ( gp.type == "time" ) {
                    re = /^\d{1,2}:\d{1,2}:\d{1,2}$/;
                    message = "Formato de hora no válido, el dato ingresado debe tener el formato hh:mm:ss, por ej. 10:00:00" ;
                } else if ( gp.type == "datetime" ) {
                    message = "Formato de fecha no válido, el dato ingresado debe tener el formato dd/mm/aaaa hh:mm:ss, por ej. 29/04/2007 10:00:00" ;
                    re = /^\d{1,2}\/\d{1,2}\/\d{4} \d{1,2}:\d{1,2}:\d{1,2}$/;
                } else if ( gp.type == "text" ) {
                    var str = GOLDStringTrim( value ) ;
                    if ( str == "" ) {
                        message = "Dato requerido no ingresado." ;
                        ret[ ret.length ] = new GOLDValidationResult( e[ i ], false, message ) ;
                    }
                }
                if ( re ) {
                  if ( value.match( re ) ) {
                      ret[ ret.length ] = new GOLDValidationResult( e[ i ], true, null ) ;
                  } else {
                      ret[ ret.length ] = new GOLDValidationResult( e[ i ], false, message ) ;
                  }
                }
            }
          }
        }
    }
    return ret ;
}

// Convierte los datos de un formulario en objeto para poder enviarlo por rpc
GOLDComponent.prototype.formToObject = function( f ) {
    var obj = new Object() ;
        var e = f.elements ;
        for ( var i = 0 ; i < e.length ; i++ ) {
            var t = e[ i ].type ;
            var value = null ;
            var name = null ;
            if ( e[ i ].name ) {
                name = e[ i ].name ;
                // select-one, radio, checkbox
                if ( t == "text" || t == "hidden" ) {
                    value = e[ i ].value ;
                } else if ( t == "radio" ) {
                    if ( e[ i ].checked ) value = e[ i ].value ;
                } else if ( t == "checkbox" ) {
                    if ( e[ i ].checked ) value = e[ i ].value ;
                } else if ( t == "select-one" ) {
                    value = e[ i ].options[ e[ i ].selectedIndex ].value ;
                } else if ( t == "hidden" ) {
                  //if ( e[ i ].value == "") value = null ;
                  //else value = e[ i ].value ;
                  value = e[ i ].value ;
                } else if ( e[ i ].value ) { // generic case (type password and other?
                    value = e[ i ].value ;
                }
                this.debug( name + ": " + obj[ name ] ) ;
            }
            if (name) {
              if (!value) value = "" ;
                if ( obj[ name ] != undefined ) {
                    if ( typeof( obj[ name ] ) == "string" ) {
                        var aux = new Array() ;
                        aux[ 0 ] = obj[ name ] ;
                        obj[ name ] = aux ;
                    }
                    obj[ name ][ obj[ name ].length++ ] = value ;
                } else {
                    obj[ name ] = value ;
                }
            }
        }
        
        return obj ;
}

GOLDComponent.prototype.objectToForm = function( f, obj ) {
	for ( var i in obj ) {
	    var e =  f.elements[ i ] ;
	    if ( e && e.type ) {
	        switch ( e.type ) {
	            case "text": 
	                e.value = obj[ i ] ;
	                break ;
	        }
	    }
	}
}

GOLDComponent.prototype.setOpacity = function( element, percent ) {
	if (element && element.style) {
	    if (element.style.opacity)
	        element.style.opacity = percent / 100 ;
	    else
	        element.style.filter = "alpha(opacity=" + percent + ")"; 
	}
}

GOLDComponent.prototype.getOpacity = function( element ) {
	return Math.round( element.style.opacity * 100 );
}

GOLDComponent.prototype.infoFadeIn = function( ) {
	var sleep = 10 ;
	var id = setInterval( this.handler + ".setOpacity( " + this.handler + ".infoLayer, " + this.handler + ".getOpacity( " + this.handler + ".infoLayer ) + 1);", sleep ) ;
	setTimeout( "clearInterval( " + id + " ) ;", sleep * 120 ) ;
}

GOLDComponent.prototype.infoFadeOut = function( ) {
	var sleep = 10 ;
	var id = setInterval( this.handler + ".setOpacity( " + this.handler + ".infoLayer, " + this.handler + ".getOpacity( " + this.handler + ".infoLayer ) - 1);", sleep ) ;
	setTimeout( "clearInterval( " + id + " ) ;", sleep * 120 ) ;
}

// TODO move this out
GOLDComponent.prototype.getNextElement = function( element ) {
	var e = null ;
	if ( element.nextSibling ) e = element.nextSibling ;
	while ( e.nodeType == 3 || e.nodeType == 8 ) {
	    if ( e.nextSibling )
	        e = e.nextSibling ;
	    else {
	        e = null ;
	        break ;
	    }
	}
	return e ;
}

GOLDComponent.prototype.getFirstChild = function( element ) {
	var e = null ;
	if ( element.firstChild ) e = element.firstChild ;
	if ( e.nodeType == 3 || e.nodeType == 8 ) 
	    e = this.getNextElement( e ) ;
	return e ;
}

GOLDComponent.prototype.showHideElement = function( element ) {
	var show = true ;
	if (element && element.style) {
	    var s = element.style ;
	    if ( s.display == "block" ) {
	        s.display = "none" ;
	        show = false ;
	
	    } else {
	        s.display = "block" ;
	    }
	    return show ;
	}
}
