
// Data object

// Laurent Fortin

// Xprima 2010


/***
 *
 * XPRIMA.data({
 *    url: string, => mandatory
 *    urlParams: object,
 *    callback: function(text, Y, context),
 *    failure: function(Y, context),
 *    context: object,
 *    method: 'GET | POST'
 * });
 *
***/


YUI().use('node', 'io', function(Y) {
  
  if(window.XPRIMA == undefined) window.XPRIMA = {};
  
  Y.aggregate(window.XPRIMA, {
  
    // main function
    data: function(cfg) {
      this._data.cfg = this._data.initConfig(cfg);
      this._data.ajaxRequest();
    },
    
    // internal info
    _data: {
      // Y instance
      Y: Y,
      // cache object
      cache: {},
      // initialize config
      initConfig: function(cfg) {
        
        if(!cfg) {
          throw('config object is mandatory');
        }
        if(!cfg.url) {
          throw('url is mandatory');
        }
        cfg.urlParams = cfg.urlParams || {};
        cfg.callback = cfg.callback || function(){};
        cfg.failure = cfg.failure || function(){};
        cfg.method = cfg.method || 'post';
        
        return cfg;
      },
      // format URL and params
      formatURIComponents: function(url, params) {
      
        var scope = this;
        
        var tmp = url.split('?');
        var url = tmp[0];
        var data = '';
        
        scope.Y.each(params, function(value, key) {
          data = data + key + '=' + encodeURIComponent(value) + '&';
        });
        
        // append inline parameters if applicable:
        if(tmp[1]) {
          data = data + tmp[1];
        }
        
        return([url, data]);
      },
      // to generate a key
      getKey: function(url) {
        
        var key = '';
        
        key += url[0].replace(/http\/\/\:|http\/\/\:/gi, '').replace(/\.|\/|\?|\%|\s/g, '_');
        key += url[1].replace(/\&/g, '_').replace(/\=/g, '_');
        
        return key;
      },
      // request
      ajaxRequest: function() {
        
        var scope = this;
        
        var tmp = scope.formatURIComponents(scope.cfg.url, scope.cfg.urlParams);
        var key = scope.getKey(tmp);
        
        if(scope.cache[key]) {
          // run callback with cache
          scope.cfg.callback(scope.cache[key], scope.Y, scope.cfg.context);
        } else {
          //console.debug(tmp);
          var ioCfg = {
            data: tmp[1],
            method: scope.cfg.method,
            on: {
              success: function(id, response, xhr) {
                // run callback
                scope.cfg.callback(response.responseText, scope.Y, this);
                // set cache
                scope.cache[this._key] = response.responseText;
              },
              failure: function(id, response, xhr) {
                scope.cfg.failure(scope.Y, this);
              }
            }
          };
          
          if(scope.cfg.context) {
            ioCfg.context = scope.cfg.context;
          } else {
            ioCfg.context = {};
          }
          scope.Y.aggregate(ioCfg.context, {_key: key});
          
          scope.Y.io(tmp[0], ioCfg);
        }
        
      }
    }
    
  });
  
});

