/**
 * JSONP Send/receive object with API
 * @class JSON
 * @constructor
 */
function JSON() {

  /**
   * Register API call
   * If not yet registered, run
   * @param {string} url API - API URL
   * @param {Function} callback - API Call back
   * @param {Object} params - Parameter to API
   */
  this.load = function(url, callback, params) {
    if (!params) {
      params = [];
    }
    params.nocache = (new Date).getTime();
    JSON.cache.push({url: url, params: params, callback: callback});
    if (JSON.cache.length == 1) {
      _loadAPI();
    }
  }

  /**
   * Call API
   */
  function _loadAPI() {
    if (JSON.cache.length) {
      var cache = JSON.cache[0];

      var url = [cache.url];
      if (cache.url.indexOf('?') == -1) {
        url.push('?');
      } else {
        url.push('&');
      }
      for (var k in cache.params) {
        url.push(k);
        url.push('=');
        url.push(cache.params[k]);
        url.push('&');
      }
      url.pop();

      /**
       * Run API callback
       * Set empty function on JSON.callback after run
       * Shift JSON.cache and Delete executed API call registration
       */
      function callback(json) {
        cache.callback(json);
        JSON.callback = function(){};
        JSON.cache.shift();
        _loadAPI();
      }
      JSON.callback = callback;
      _loadWithDelay(url.join(''));
    }
  }

  /**
   * Call API
   * asynchronous separation - for Opera
   */
  function _loadWithDelay(url) {
    function timeout() {
      _writeJSONTag(url);
    }
    setTimeout(timeout, 10);
  }

  /**
   * Call API
   * Write script tag
   */
  function _writeJSONTag(url) {
    var jsonScript = document.getElementById('jsonScript');
    if (jsonScript) {
      jsonScript.parentNode.removeChild(jsonScript);
    }
    var script = document.createElement('script');
    script.setAttribute('src', url);
    script.setAttribute('id', 'jsonScript');
    script.setAttribute('type', 'text/javascript');
    script.setAttribute('charset', 'utf-8');
    document.documentElement.firstChild.appendChild(script);
  }
}
/**
 * Array that keeps API call registration
 */
JSON.cache = [];
/**
 * Callback tied to recently called API
 */
JSON.callback = function(){};

/**
 * Fix the API call back function name to 'callback'
 */
function callback(json) {
  JSON.callback(json);
}

