/*
 * Ext JS Library 2.0
 * Copyright(c) 2006-2007, Ext JS, LLC.
 * licensing@extjs.com
 *
 * http://extjs.com/license
 */

/**
 * Create a new instance of SoapConnection
 * 
 * @classDescription		This class is used to create a new connection 
 * 							using WSDL mozilla API.
 * @param {Object} config
 * @constructor
 */
Ext.data.SoapConnection = function(config){

    Ext.apply(this, config);
    Ext.data.SoapConnection.superclass.constructor.call(this);
    
    this.port = config.port || this.method + 'Port';
    this.proxy = null;
    
    this.listener = {
        scope: this,
        onLoad: function(aProxy){
            this.scope.proxy = aProxy;
            this.scope.proxy.setListener(this);
            // Add the abord related things..
        },
        onError: function(aError){
            alert("Error: " + aError);
        }
    };
    
    if (typeof this.method == "string") 
        this.method = new Array(this.method);
    for (i in this.method) 
        this.listener[this.method[i] + 'Callback'] = function(aresult){
            Ext.callback(this.proceedMe, this.scope, [this.proceedOption, true, aresult]);
        };
    
    this.factory = new WebServiceProxyFactory();
    this.factory.createProxyAsync(this.url, this.port, "", true, this.listener);
    
}

Ext.extend(Ext.data.SoapConnection, Ext.data.Connection, {

    // public function request( [Object options] )
    // option : Object
    //	url			{String} (Optional) The URL to which to send the request. Defaults to configured URL
    //	params		{Object/String/Function} (Optional) An object containing properties which are used as parameters to the request.
    //	method		{String} The method to use for the request.
    //	port		{String} (Optional) The name of the port of the service that this service proxy represents. Currently the port must represent a SOAP binding. 
    //	callback	{Function} (Optional) The function to be called upon receipt of the HTTP response. The callback is called regardless of success or failure and is passed the following parameters:
    //		options		{Object} The parameter to the request call.
    //		success		{Boolean} True if the request succeeded.
    //		response	{Object} The XMLHttpRequest object containing the response data.
    //	success		{Function} (Optional) The function to be called upon success of the request. The callback is passed the following parameters:
    //		response	{Object} The WSDL object containing the response data.
    //		options		{Object} The parameter to the request call.
    //	failure		{Function} (Optional) The function to be called upon failure of the request. The callback is passed the following parameters:
    //		response	{Object} The XMLHttpRequest object containing the response data.
    //		options		{Object} The parameter to the request call.
    //	scope		{Object} (Optional) The scope in which to execute the callbacks: The "this" object for the callback function. Defaults to the browser window.
    //	form		{Object/String} (Optional) A form object or id to pull parameters from.
    //
    // Return : Number
    //	transactionId
    request: function(o){
        if (this.fireEvent("beforerequest", this, o) !== false && this.proxy) {
        
            if (typeof o.params == "function") {
                p = p.call(o.scope || window, o);
            }
            
            var p = o.params;
            
            var method = o.method || this.method;
            
            if (!p.page) 
                p.page = 1;
            //var port		= options.port 		|| method+'Port'; // Test if the method is'nt an object.
            
            var callback = o.callback || this.callback;
            var success = o.success || this.success;
            var scope = o.scope || this.scope;
            
            netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
            
            this.listener.proceedMe = callback;
            this.listener.proceedOption = o;
            
            this.proxy[method].call(this.proxy, p);
            
        }
        else {
            Ext.callback(o.callback, this, [o, null, null]);
        }
    }
});


Ext.data.SoapProxy = function(config){
    Ext.data.SoapProxy.superclass.constructor.call(this);
    this.conn = new Ext.data.SoapConnection(config);
};

Ext.extend(Ext.data.SoapProxy, Ext.data.DataProxy, {
    
	/**
	 * memberOf Ext.data.SoapProxy
	 */
	getConnection: function(){
        return this.conn;
    },
    
	/**
	 * @memberOf Ext.data.SoapProxy
	 * @method
	 * @param {Object} params
	 * @param {Object} reader
	 * @param {Object} callback
	 * @param {Object} scope
	 * @param {Object} arg
	 */
    load: function(params, reader, callback, scope, arg){
        if (this.fireEvent("beforeload", this, params) !== false) {
            //for (newParams in this.conn.param)
            //	params[newParams] = this.conn.param[newParams];
            var o = {
                params: params ||
                {},
                request: {
                    callback: callback,
                    scope: scope,
                    arg: arg
                },
                reader: reader,
                callback: this.loadResponse,
                scope: this
            };
            this.conn.request(o);
        }
        else {
            callback.call(scope || this, null, arg, false);
        }
    },
    
    /**
     * @memberOf Ext.SoapProxy
     * @method
     * @param {Object} o
     * @param {Object} success
     * @param {Object} response
     */
    loadResponse: function(o, success, response){
        delete this.activeRequest;
        if (!success) {
            this.fireEvent("loadexception", this, o, response);
            o.request.callback.call(o.request.scope, null, o.request.arg, false);
            return;
        }
        var result;
        try {
            result = o.reader.read(response);
        } 
        catch (e) {
            this.fireEvent("loadexception", this, o, response, e);
            o.request.callback.call(o.request.scope, null, o.request.arg, false);
            return;
        }
        this.fireEvent("load", this, o, o.request.arg);
        o.request.callback.call(o.request.scope, result, o.request.arg, true);
    },
    
    /**
     * @memberOf Ext.data.SoapProxy
     * @param {Object} dataSet
     */
    update: function(dataSet){
    
    },
    
    /**
     * @memberOf Ext.data.SoapProxy
     * @param {Object} dataSet
     */
    updateResponse: function(dataSet){
    
    }
});

Ext.data.SoapReader = function(meta, recordType){
    meta = meta ||
    {};
    Ext.data.SoapReader.superclass.constructor.call(this, meta, recordType || meta.fields);
};

Ext.extend(Ext.data.SoapReader, Ext.data.DataReader, {
    read: function(request){
        // Look at the RecordType and the Id.
        var recordType = this.recordType, fields = recordType.prototype.fields;
        var sid = this.meta.id;
        
        var TotalRecords = 1, success = true;
        if (this.meta.totalRecords) 
            TotalRecords = request[this.meta.totalRecords];
        //else if (this.meta.record)
        //	TotalRecords = request[this.meta.record].length;
        
        var records = [];
        var rows = request[this.meta.record] || request;
        
        if (TotalRecords != 0) {
            for (i = 0; i < rows.length; i++) {
                var row = rows[i];
                var values = {};
                var id = sid ? row[sid] : undefined;
                for (var j = 0, jlen = fields.length; j < jlen; j++) {
                    var f = fields.items[j];
                    var v = row[f.mapping || f.name];
                    v = typeof v == 'Object' ? v : f.convert(v);
                    values[f.name] = v;
                }
                var record = new recordType(values, id);
                record.node = row;
                records[records.length] = record;
            }
        }
        return {
            success: success,
            records: records,
            totalRecords: TotalRecords || records.length
        };
    }
});
