/**
 * Привязка кнопок сохранения/загрузки памяти на главной странице index.html.
 *
 * Назначение:
 * - Подключает обработчики к кнопкам "Сохранить память" и "Загрузить память".
 * - Сбор и применение данных идут через единый реестр BEAST.persistentModules:
 *   один массив пар «ключ в JSON ↔ serialize/apply», добавление нового модуля = одна запись.
 *
 * Порядок и DOM: скрипты подключаются в конце body; при переносе в head нужно
 * вызывать init только после готовности DOM (DOMContentLoaded или аналог).
 *
 * Зависимости (должны быть подключены до этого скрипта):
 * - beast/date/saving_all/saving_all.js (handle_save_memory_click, load_all_memory)
 * - beast/puls.js (Cur_puls_val, update_beast_pulse_view)
 *
 * Ожидаемые id в index.html: btnSaveMemory, btnLoadMemory.
 */

(function (global) {
  'use strict';

  var PULSE_KEY = 'Cur_puls_val';

  if (!global.BEAST) global.BEAST = {};
  /**
   * Реестр сохраняемых модулей. Каждый элемент: { key, serialize, apply }.
   * key — поле в JSON при сохранении в файл.
   * serialize() — возвращает значение для сохранения (или undefined, тогда ключ не пишется).
   * apply(data) — применяет загруженное значение; вызывается только если в loaded есть этот ключ.
   * Добавление нового хранилища = одна запись здесь, без правок collect_memory_data/apply_loaded_memory.
   */
  var persistentModules = [];
  global.BEAST.persistentModules = persistentModules;

  persistentModules.push({
    key: 'Cur_puls_val',
    serialize: function () {
      return global.Cur_puls_val;
    },
    apply: function (value) {
      var n = parseInt(value, 10);
      if (isNaN(n) || n < 0) return;
      global.Cur_puls_val = n;
      try {
        global.localStorage.setItem(PULSE_KEY, String(global.Cur_puls_val));
      } catch (e) {}
      if (typeof global.update_beast_pulse_view === 'function') {
        global.update_beast_pulse_view();
      }
    }
  });

  persistentModules.push({
    key: 'VitalsValues',
    serialize: function () {
      if (!global.VitalsArr || !global.VitalsArr.length) return undefined;
      var values = [];
      for (var i = 0; i < global.VitalsArr.length; i++) {
        values.push(global.VitalsArr[i].value);
      }
      return values;
    },
    apply: function (values) {
      if (!global.VitalsArr || !Array.isArray(values)) return;
      for (var i = 0; i < global.VitalsArr.length && i < values.length; i++) {
        var v = parseFloat(values[i]);
        if (isNaN(v)) continue;
        if (v < 0) v = 0;
        if (v > 100) v = 100;
        global.VitalsArr[i].value = v;
      }
      if (typeof global.saveVitalsToStorage === 'function') {
        global.saveVitalsToStorage();
      }
      if (typeof global.update_vitals_view === 'function') {
        global.update_vitals_view();
      }
    }
  });

  persistentModules.push({
    key: 'SemanticState',
    serialize: function () {
      if (typeof global.serializeSemanticState !== 'function') return undefined;
      return global.serializeSemanticState();
    },
    apply: function (data) {
      if (typeof global.applySemanticState !== 'function') return;
      global.applySemanticState(data);
    }
  });

  persistentModules.push({
    key: 'ConditionalReflexesState',
    serialize: function () {
      if (typeof global.serializeConditionalReflexesState !== 'function') return undefined;
      return global.serializeConditionalReflexesState();
    },
    apply: function (data) {
      if (typeof global.applyConditionalReflexesState !== 'function') return;
      global.applyConditionalReflexesState(data);
    }
  });

  persistentModules.push({
    key: 'PerceptionTreeState',
    serialize: function () {
      if (typeof global.PerceptionTree_serializeState !== 'function') return undefined;
      return global.PerceptionTree_serializeState();
    },
    apply: function (data) {
      if (typeof global.PerceptionTree_applyState !== 'function') return;
      global.PerceptionTree_applyState(data);
    }
  });

  persistentModules.push({
    key: 'ActionImagesState',
    serialize: function () {
      if (typeof global.ActionImages_serializeState !== 'function') return undefined;
      return global.ActionImages_serializeState();
    },
    apply: function (data) {
      if (typeof global.ActionImages_applyState !== 'function') return;
      global.ActionImages_applyState(data);
    }
  });

  persistentModules.push({
    key: 'EpisodesState',
    serialize: function () {
      if (typeof global.EpisodicMemory_serializeState !== 'function') return undefined;
      return global.EpisodicMemory_serializeState();
    },
    apply: function (data) {
      if (typeof global.EpisodicMemory_applyState !== 'function') return;
      global.EpisodicMemory_applyState(data);
    }
  });

  persistentModules.push({
    key: 'AutomatizmsState',
    serialize: function () {
      if (typeof global.Automatizms_serializeState !== 'function') return undefined;
      return global.Automatizms_serializeState();
    },
    apply: function (data) {
      if (typeof global.Automatizms_applyState !== 'function') return;
      global.Automatizms_applyState(data);
    }
  });

  persistentModules.push({
    key: 'GoalImagesState',
    serialize: function () {
      if (typeof global.Goals_serializeState !== 'function') return undefined;
      return global.Goals_serializeState();
    },
    apply: function (data) {
      if (typeof global.Goals_applyState !== 'function') return;
      global.Goals_applyState(data);
    }
  });

  persistentModules.push({
    key: 'SituationsTreeState',
    serialize: function () {
      if (typeof global.SituationsTree_serializeState !== 'function') return undefined;
      return global.SituationsTree_serializeState();
    },
    apply: function (data) {
      if (typeof global.SituationsTree_applyState !== 'function') return;
      global.SituationsTree_applyState(data);
    }
  });

  persistentModules.push({
    key: 'MentalAutomatizmsState',
    serialize: function () {
      if (typeof global.MentalAutomatizms_serializeState !== 'function') return undefined;
      return global.MentalAutomatizms_serializeState();
    },
    apply: function (data) {
      if (typeof global.MentalAutomatizms_applyState !== 'function') return;
      global.MentalAutomatizms_applyState(data);
    }
  });

  persistentModules.push({
    key: 'AbstractImagesState',
    serialize: function () {
      if (typeof global.AbstractImages_serializeState !== 'function') return undefined;
      return global.AbstractImages_serializeState();
    },
    apply: function (data) {
      if (typeof global.AbstractImages_applyState !== 'function') return;
      global.AbstractImages_applyState(data);
    }
  });

  /**
   * Собрать объект данных для сохранения в файл.
   * Проход по реестру persistentModules, вызов serialize() у каждого модуля.
   */
  function collect_memory_data() {
    var data = {};
    var list = global.BEAST.persistentModules;
    if (!Array.isArray(list)) return data;
    for (var i = 0; i < list.length; i++) {
      var mod = list[i];
      if (!mod || !mod.key) continue;
      try {
        var value = mod.serialize();
        if (value !== undefined) {
          data[mod.key] = value;
        }
      } catch (e) {
        if (typeof global.console !== 'undefined' && global.console.error) {
          global.console.error('collect_memory_data:', mod.key, e);
        }
      }
    }
    return data;
  }

  /**
   * Применить загруженные из файла данные.
   * Проход по реестру persistentModules, вызов apply(loaded[key]) при наличии ключа.
   * Ошибки не скрываются: каждая исключение логируется в консоль, ключ попадает в массив ошибок.
   * Возвращает массив ключей, по которым apply выбросил ошибку (для сообщения пользователю).
   */
  function apply_loaded_memory(loaded) {
    var errors = [];
    if (!loaded || typeof loaded !== 'object') return errors;
    var list = global.BEAST.persistentModules;
    if (!Array.isArray(list)) return errors;
    for (var i = 0; i < list.length; i++) {
      var mod = list[i];
      if (!mod || !mod.key || loaded[mod.key] === undefined) continue;
      if (typeof mod.apply !== 'function') continue;
      try {
        mod.apply(loaded[mod.key]);
      } catch (e) {
        if (typeof global.console !== 'undefined' && global.console.error) {
          global.console.error('apply_loaded_memory:', mod.key, e);
        }
        errors.push(mod.key);
      }
    }
    return errors;
  }

  function init() {
    var btnSave = global.document.getElementById('btnSaveMemory');
    var btnLoad = global.document.getElementById('btnLoadMemory');

    if (btnSave && typeof global.handle_save_memory_click === 'function') {
      btnSave.addEventListener('click', function () {
        global.handle_save_memory_click(collect_memory_data);
      });
    }

    if (btnLoad && typeof global.load_all_memory === 'function') {
      btnLoad.addEventListener('click', function () {
        global.load_all_memory()
          .then(function (loaded) {
            var errors = apply_loaded_memory(loaded);
            if (typeof global.show_alert === 'function') {
              if (errors.length) {
                global.show_alert('Память загружена с ошибками в части данных: ' + errors.join(', ') + '. Проверьте консоль.', 0);
              } else {
                global.show_alert('Память успешно загружена из файла.', 2000);
              }
            }
          })
          .catch(function (error) {
            if (error && error.name === 'AbortError') return;
            if (typeof global.show_alert === 'function') {
              global.show_alert('Ошибка при загрузке памяти: ' + (error && error.message ? error.message : String(error)), 0);
            }
          });
      });
    }
  }

  if (global.document.readyState === 'loading') {
    global.document.addEventListener('DOMContentLoaded', init);
  } else {
    init();
  }
})(window);
