/* Модели понимания образов (FinalImage).
 *
 * Для заданного finalImageId необходимо уметь получить временный массив
 * всех семантических "кадров" памяти (SemanticObjectImportance) во всех
 * условиях (WellNormaBad, EmotionId), в которых этот образ встречался.
 *
 * На основе этой выборки строится модель понимания образа:
 * ImageUnderstandingModelArr[finalImageId] — массив записей, каждая из которых
 * содержит сводную информацию по одному сочетанию условий.
 */

(function (global) {
  'use strict';

  // Глобальный массив моделей понимания образов.
  // Индекс: ImageUnderstandingModelArr[finalImageId] = модель или undefined.
  if (!global.ImageUnderstandingModelArr) {
    global.ImageUnderstandingModelArr = {};
  }

  var MULTIPLIER = (typeof global.StimulusGlobalId_MULTIPLIER === 'number') ? global.StimulusGlobalId_MULTIPLIER : 1000;

  /**
   * Для образа с глобальными stimulIds (например [2010]) возвращает id других FinalImage,
   * у которых stimulIds в старом формате (например [10]). Нужно для слияния кадров после перехода на глобальные id.
   */
  function getLegacyEquivalentFinalImageIds(finalImageId) {
    var ids = [];
    if (!Array.isArray(global.FinalImages)) return ids;
    var current = null;
    for (var i = 0; i < global.FinalImages.length; i++) {
      if (global.FinalImages[i] && global.FinalImages[i].id === finalImageId) {
        current = global.FinalImages[i];
        break;
      }
    }
    if (!current || !Array.isArray(current.stimulIds) || !current.stimulIds.length) return ids;
    var legacy = [];
    for (var j = 0; j < current.stimulIds.length; j++) {
      var s = current.stimulIds[j];
      var v = parseInt(s, 10);
      if (isNaN(v) || v <= 0) continue;
      legacy.push(v >= MULTIPLIER ? v % MULTIPLIER : v);
    }
    legacy.sort(function (a, b) { return a - b; });
    for (var k = 0; k < global.FinalImages.length; k++) {
      var im = global.FinalImages[k];
      if (!im || im.id === finalImageId || !Array.isArray(im.stimulIds)) continue;
      var other = im.stimulIds.slice(0).sort(function (a, b) { return a - b; });
      if (other.length !== legacy.length) continue;
      var eq = true;
      for (var n = 0; n < legacy.length; n++) {
        if (other[n] !== legacy[n]) { eq = false; break; }
      }
      if (eq) ids.push(im.id);
    }
    return ids;
  }

  /**
   * Получить выборку всех семантических кадров для данного finalImageId
   * во всех условиях (по всему SemanticMemory).
   * Учитываются и кадры, записанные под «legacy»-образами (со старыми локальными stimulIds),
   * чтобы не терять данные после перехода на глобальные id стимулов.
   *
   * @param {number} finalImageId
   * @returns {Array<Object>} массив объектов SemanticObjectImportance,
   *          отфильтрованных по finalImageId и эквивалентным legacy-образам.
   */
  function getSemanticFramesForFinalImage(finalImageId) {
    var result = [];
    var getFrames = global.getSemanticFramesForFinalImageId;
    if (typeof getFrames !== 'function') return result;
    var idsToInclude = [finalImageId].concat(getLegacyEquivalentFinalImageIds(finalImageId));
    for (var i = 0; i < idsToInclude.length; i++) {
      var frames = getFrames(idsToInclude[i]);
      if (frames && frames.length) {
        for (var j = 0; j < frames.length; j++) result.push(frames[j]);
      }
    }
    return result;
  }

  /**
   * Построить (или обновить) модель понимания образа для заданного finalImageId.
   *
   * Модель представляет собой массив сводных записей по всем найденным
   * сочетаниям (wellNormaBad, emotionId) для этого FinalImage:
   * [
   *   {
   *     wellNormaBad: 1|2|3,
   *     emotionId: number,
   *     meanImportance: number,
   *     samplesCount: number,
   *     lastImportance: number
   *   },
   *   ...
   * ]
   *
   * @param {number} finalImageId
   * @returns {Array<Object>} модель понимания для данного finalImageId.
   */
  function buildImageUnderstandingModel(finalImageId) {
    var frames = getSemanticFramesForFinalImage(finalImageId);
    var model = [];
    for (var i = 0; i < frames.length; i++) {
      var f = frames[i];
      model.push({
        wellNormaBad: f.wellNormaBad,
        emotionId: f.emotionId,
        meanImportance: f.meanImportance,
        samplesCount: f.samplesCount,
        lastImportance: f.lastImportance
      });
    }
    global.ImageUnderstandingModelArr[finalImageId] = model;
    return model;
  }

  /**
   * Получить уже построенную модель понимания образа, не пересчитывая её.
   * Если модели нет, она будет построена на основе текущей SemanticMemory.
   *
   * @param {number} finalImageId
   * @returns {Array<Object>} модель понимания.
   */
  function getImageUnderstandingModel(finalImageId) {
    var model = global.ImageUnderstandingModelArr[finalImageId];
    if (!model) {
      model = buildImageUnderstandingModel(finalImageId);
    }
    return model;
  }

  // Экспорт в глобальную область
  global.getSemanticFramesForFinalImage = getSemanticFramesForFinalImage;
  global.buildImageUnderstandingModel = buildImageUnderstandingModel;
  global.getImageUnderstandingModel = getImageUnderstandingModel;

})(window);

