/**
 * The library list cache
 *
 * @type Object
 */
var llc = H5PEditor.LibraryListCache = {
  libraryCache: {},
  librariesComingIn: {},
  librariesMissing: {},
  que: []
};

/**
 * Get data for a list of libraries
 *
 * @param {Array} libraries - list of libraries to load info for (uber names)
 * @param {Function} handler - Callback when list of libraries is loaded
 * @param {Function} [thisArg] - Context for the callback function
 */
llc.getLibraries = function (libraries, handler, thisArg) {
  // Determine whether we're dealing with simple library strings or objects
  libraries = libraries.map(function (option) {
    return (typeof option === 'object') ? option.name : option;
  });

  var cachedLibraries = [];
  var status = 'hasAll';
  for (var i = 0; i < libraries.length; i++) {
    if (libraries[i] in llc.libraryCache) {
      // Libraries that are missing on the server are set to null...
      if (llc.libraryCache[libraries[i]] !== null) {
        cachedLibraries.push(llc.libraryCache[libraries[i]]);
      }
    }
    else if (libraries[i] in llc.librariesComingIn) {
      if (status === 'hasAll') {
        status = 'onTheWay';
      }
    }
    else {
      status = 'requestThem';
      llc.librariesComingIn[libraries[i]] = true;
    }
  }
  switch (status) {
    case 'hasAll':
      handler.call(thisArg, cachedLibraries);
      break;
    case 'onTheWay':
      llc.que.push({libraries: libraries, handler: handler, thisArg: thisArg});
      break;
    case 'requestThem':
      var ajaxParams = {
        type: "POST",
        url: H5PEditor.getAjaxUrl('libraries'),
        success: function (data) {
          llc.setLibraries(data, libraries);
          handler.call(thisArg, data);
          llc.runQue();
        },
        data: {
          'libraries': libraries
        },
        dataType: "json"
      };
      H5PEditor.$.ajax(ajaxParams);
      break;
  }
};

/**
 * Call all qued handlers
 */
llc.runQue = function () {
  var l = llc.que.length;
  for (var i = 0; i < l; i++) {
    var handlerObject = llc.que.shift();
    llc.getLibraries(handlerObject.libraries, handlerObject.handler, handlerObject.thisArg);
  }
};

/**
 * We've got new libraries from the server, save them
 *
 * @param {Array} libraries - Libraries with info from server
 * @param {Array} requestedLibraries - List of what libraries we requested
 */
llc.setLibraries = function (libraries, requestedLibraries) {
  var reqLibraries = requestedLibraries.slice();
  for (var i = 0; i < libraries.length; i++) {
    llc.libraryCache[libraries[i].uberName] = libraries[i];
    if (libraries[i].uberName in llc.librariesComingIn) {
      delete llc.librariesComingIn[libraries[i].uberName];
    }
    var index = reqLibraries.indexOf(libraries[i].uberName);
    if (index > -1) {
      reqLibraries.splice(index, 1);
    }
  }
  for (i = 0; i < reqLibraries.length; i++) {
    llc.libraryCache[reqLibraries[i]] = null;
    if (reqLibraries[i] in llc.librariesComingIn) {
      delete llc.librariesComingIn[libraries[i]];
    }
  }
};

/**
 * Creates a default content title, based on the title of the library
 * @param  {String} uberName "<machineName> <major>.<minor>"
 * @return {String}
 */
llc.getDefaultTitle = function (uberName) {
  var libraryMetadata = llc.libraryCache[uberName];
  var title = libraryMetadata && libraryMetadata.title ? libraryMetadata.title : '';
  return H5PEditor.t('core', 'untitled').replace(':libraryTitle', title);
};
