/**
 * @file Provides functionality to handle portal details, including caching and server requests.
 * @namespace window.portalDetail
 */

var cache;
var requestQueue = {};

window.portalDetail = function () {};

/**
 * Sets up the portal detail handler, initializing the cache.
 *
 * @function window.portalDetail.setup
 */
window.portalDetail.setup = function () {
  cache = new window.DataCache();

  cache.startExpireInterval(20);
};

/**
 * Retrieves portal details from cache by GUID.
 *
 * @function window.portalDetail.get
 * @param {string} guid - The Global Unique Identifier of the portal.
 * @returns Cached portal details if available.
 */
window.portalDetail.get = function (guid) {
  return cache.get(guid);
};

/**
 * Stores portal details in the cache.
 *
 * @function window.portalDetail.store
 * @param {string} guid - The Global Unique Identifier of the portal.
 * @param {object} dict - The portal detail data.
 * @returns Result of cache storage operation.
 */
window.portalDetail.store = function (guid, dict) {
  return cache.store(guid, dict);
};

/**
 * Checks if portal details are fresh in the cache.
 *
 * @function window.portalDetail.isFresh
 * @param {string} guid - The Global Unique Identifier of the portal.
 * @returns {boolean} True if details are fresh, false otherwise.
 */
window.portalDetail.isFresh = function (guid) {
  return cache.isFresh(guid);
};

window.portalDetail.remove = function (guid) {
  return cache.remove(guid);
};

var handleResponseSuccess = function (deferred, guid, data, prefetch) {
  if (!data || data.error || !data.result) {
    handleResponseFailure(deferred, guid, data);
    return;
  }

  // Parse portal details
  var dict = window.decodeArray.portal(data.result, 'detailed');
  cache.store(guid, dict);

  // entity format, as used in map data
  var ent = [guid, data.result[13], data.result];
  var portal = window.mapDataRequest.render.createPortalEntity(ent, 'detailed');

  deferred.resolve(portal.options.data);
  window.runHooks('portalDetailLoaded', { guid: guid, success: true, details: portal.options.data, ent: ent, portal: portal });

  // prefetch portal image
  if (prefetch && portal.options.data.image) {
    new Image().src = portal.options.data.image;
  }
};

var handleResponseFailure = function (deferred, guid, data) {
  if (data && data.error === 'RETRY') {
    // server asked us to try again
    doRequest(deferred, guid);
  } else {
    deferred.reject();
    window.runHooks('portalDetailLoaded', { guid: guid, success: false });
  }
};

var doRequest = function (deferred, guid, prefetch) {
  window.postAjax(
    'getPortalDetails',
    { guid: guid },
    function (data) {
      handleResponseSuccess(deferred, guid, data, prefetch);
    },
    function () {
      handleResponseFailure(deferred, guid);
    }
  );
};

/**
 * Requests detailed information for a specific portal. If the information is not already being requested,
 * it initiates a new request. Returns a promise that resolves with the portal details.
 *
 * @function window.portalDetail.request
 * @param {string} guid - The Global Unique Identifier of the portal.
 * @returns {Promise} A promise that resolves with the portal details upon successful retrieval or rejection on failure.
 */
window.portalDetail.request = function (guid, prefetch = false) {
  if (!requestQueue[guid]) {
    var deferred = $.Deferred();
    requestQueue[guid] = deferred.promise();
    deferred.always(function () {
      delete requestQueue[guid];
    });

    doRequest(deferred, guid, prefetch);
  }

  return requestQueue[guid];
};