/**
 * A base provider for communicating using JSON. This is an abstract class
 * and should not be instanced directly.
 *
 * @abstract
 */
Ext.define('Ext.direct.JsonProvider', {
    extend: 'Ext.direct.Provider',
    alias:  'direct.jsonprovider',

    uses: [
        'Ext.direct.ExceptionEvent',
        'Ext.direct.Manager'
    ],

    /**
    * Parse the JSON response
    * @private
    *
    * @param {Object} response The XHR response object
    *
    * @return {Object} The data in the response.
    */
    parseResponse: function(response) {
        var text = response && response.responseText;
        
        // Empty string should blow up in JSON decoder
        if (text != null) {
            if (Ext.isObject(text) || Ext.isArray(text)) {
                return text;
            }

            return Ext.decode(text);
        }

        return null;
    },

    /**
     * Creates a set of events based on the XHR response
     *
     * @param {Object} response The XHR response
     *
     * @return {Ext.direct.Event[]} An array of Ext.direct.Event
     */
    createEvents: function(response) {
        var me = this,
            data = null,
            events = [],
            event, i, len;

        try {
            data = me.parseResponse(response);
        }
        catch (e) {
            event = new Ext.direct.ExceptionEvent({
                parsingError: true,
                data: e,
                xhr: response,
                code: Ext.direct.Manager.exceptions.PARSE,
                message: 'Error parsing json response: \n\n ' + e
            });

            return [event];
        }

        if (Ext.isArray(data)) {
            for (i = 0, len = data.length; i < len; ++i) {
                events.push(me.createEvent(data[i]));
            }
        }
        else if (Ext.isObject(data)) {
            events.push(me.createEvent(data));
        }

        return events;
    },

    /**
     * Create an event from a response object
     *
     * @param {Object} response Response object
     *
     * @return {Ext.direct.Event} The event
     */
    createEvent: function(response) {
        if (typeof response !== 'object'|| !('type' in response)) {
            return new Ext.direct.ExceptionEvent({
                data: response,
                code: Ext.direct.Manager.exceptions.DATA,
                message: 'Invalid data: event type is not specified'
            });
        }
    
        return Ext.create('direct.' + response.type, response);
    }
});
