﻿var Ext = Ext || {};
Ext.data = Ext.data || {};

Ext.data.DiffgramReader = function(meta, recordType) {
    meta = meta || {};
    Ext.data.DiffgramReader.superclass.constructor.call(this, meta, recordType || meta.fields);
};
Ext.extend(Ext.data.DiffgramReader, Ext.data.DataReader, {
    /**
    * This method is only used by a DataProxy which has retrieved data from a remote server.
    * @param {Object} response The XHR object which contains the parsed XML document.  The response is expected
    * to contain a property called <tt>responseXML</tt> which refers to an XML document object.
    * @return {Object} records A data block which is used by an {@link Ext.data.Store} as
    * a cache of Ext.data.Records.
    */
    "read": function(response) {
        var doc = response.responseXML;
        if (!doc) {
            throw { message: "DiffgramReader.read: XML Document not available" };
        }
        return this.readRecords(doc);
    },

    /**
    * Create a data block containing Ext.data.Records from an XML document.
    * @param {Object} doc A parsed XML document.
    * @return {Object} records A data block which is used by an {@link Ext.data.DiffgramStore} as
    * a cache of Ext.data.Records.
    */
    "readRecords": function(doc) {
        /**
        * After any data loads/reads, the raw XML Document is available for further custom processing.
        * @type XMLDocument
        */
        this.xmlData = doc;
        var root = doc.documentElement || doc;
		//replace Ext.DomQuery with the namespace-aware selectSingleNode and selectNodes
		//also supply custom versions of selectNumber, selectValue
		var selectValue = function(path, root, defaultValue) {
			var trimRe = /^\s+|\s+$/g;
			path = path.replace(trimRe, "");
			var n = root.selectSingleNode(path);
			var v;
			if(n) {
				//check if n is an attribute
				if(n.nodeType && n.nodeType == 2) {
					v = n.value;
				}
				else {
					v = (n && n.firstChild ? n.firstChild.nodeValue : null);
				}
			}
            return ((v === null||v === undefined||v==='') ? defaultValue : v);
		}
		var selectNumber = function(path, root, defaultValue) {
            var v = Ext.DomQueryNS.selectValue(path, root, defaultValue || 0);
            return parseFloat(v);
		}
		
        var recordType = this.recordType, fields = recordType.prototype.fields;
        var sid = this.meta.id;
        var totalRecords = 0, success = true;
        if (this.meta.totalRecords) {
			totalRecords = q.selectNumber(this.meta.totalRecords, root, 0);
        }

        if (this.meta.success) {
            var sv = selectValue(this.meta.success, root, true);
            success = sv !== false && sv !== 'false';
        }
        var records = [];
		var ns = root.selectNodes(this.meta.record);
        for (var i = 0, len = ns.length; i < len; i++) {
            var n = ns[i];
            var values = {};
            var id = sid ? selectValue(sid, n) : undefined;
            for (var j = 0, jlen = fields.length; j < jlen; j++) {
                var f = fields.items[j];
                var v = selectValue(f.mapping || f.name, n, f.defaultValue);
                v = f.convert(v, n);
                values[f.name] = v;
            }
            var record = new recordType(values, id);
            record.node = n;
            records[records.length] = record;
        }

        return {
            "success": success,
            "records": records,
            "totalRecords": totalRecords || records.length
        };
    }
});
