/**
 * Модуль полной выгрузки и загрузки памяти существа в локальный файл
 * по выбору пользователя (File System Access API).
 *
 * Назначение:
 * - По команде из index.html (кнопка «Сохранить память») сохраняет данные
 *   в файл, который пользователь выбирает через диалог (window.showSaveFilePicker).
 * - Позволяет загрузить ранее сохранённые данные из файла, выбранного
 *   пользователем (window.showOpenFilePicker).
 *
 * Требования:
 * - File System Access API полностью поддерживается в Chrome.
 * - В браузерах без поддержки API при попытке сохранения/загрузки
 *   выводится сообщение (show_alert): данный браузер не поддерживает
 *   сохранение памяти, необходимо использовать Chrome.
 *
 * Основные функции:
 * - save_all_memory(data)     — сохранение данных в файл (диалог выбора места).
 * - load_all_memory()         — загрузка данных из выбранного пользователем файла.
 * - handle_save_memory_click(collectDataFn) — обработчик кнопки «Сохранить память».
 *
 * Примеры использования (в index.html):
 *
 *   // Кнопка «Сохранить память»:
 *   document.getElementById('btnSaveMemory').addEventListener('click', function () {
 *     handle_save_memory_click(function collectData() {
 *       return { timestamp: Date.now(), version: 1 };
 *     });
 *   });
 *
 *   // Загрузка сохранённых данных (например, кнопка «Загрузить память»):
 *   load_all_memory()
 *     .then(function (loaded) {
 *       // здесь применить загруженные данные
 *     })
 *     .catch(function (error) {
 *       console.error(error);
 *     });
 */

(function (global) {
  'use strict';

  // Рекомендуемое расширение и описание для диалога сохранения
  var SAVE_DEFAULT_NAME = 'beast_memory.json';
  var SAVE_ACCEPT = { 'application/json': ['.json'] };

  /**
   * Проверка поддержки File System Access API (showSaveFilePicker).
   * @returns {boolean}
   */
  function is_file_system_access_supported() {
    return typeof global.showSaveFilePicker === 'function';
  }

  /**
   * Сообщение пользователю о неподдерживаемом браузере.
   */
  function alert_unsupported_browser() {
    if (typeof global.show_alert === 'function') {
      global.show_alert(
        'Данный браузер не поддерживает сохранение памяти. Используйте Chrome.',
        0
      );
    }
  }

  /**
   * Сохранение данных в файл по выбору пользователя (File System Access API).
   * Использует последнюю выбранную папку (startIn), если она сохранена в IndexedDB.
   *
   * @param {Object} data - объект с памятью существа (будет сериализован в JSON).
   * @returns {Promise<void>} - выполняется после успешной записи.
   */
  function save_all_memory(data) {
    if (!is_file_system_access_supported()) {
      alert_unsupported_browser();
      return Promise.reject(new Error('File System Access API не поддерживается.'));
    }
    if (typeof global.showSaveIndicator === 'function') global.showSaveIndicator();

    var payloadString;
    try {
      payloadString = JSON.stringify(data || {}, null, 2);
    } catch (e) {
      if (typeof global.hideSaveIndicator === 'function') global.hideSaveIndicator();
      return Promise.reject(new Error('Не удалось сериализовать данные: ' + e.message));
    }

    var pickerOptions = {
      suggestedName: SAVE_DEFAULT_NAME,
      types: [{ description: 'JSON', accept: SAVE_ACCEPT }]
    };

    var startInPromise = typeof global.loadLastMemoryDirectory === 'function'
      ? global.loadLastMemoryDirectory()
      : Promise.resolve(undefined);

    return startInPromise
      .then(function (startIn) {
        if (startIn) pickerOptions.startIn = startIn;
        return global.showSaveFilePicker(pickerOptions);
      })
      .then(function (handle) {
        return handle.createWritable().then(function (writable) {
          return writable.write(payloadString)
            .then(function () {
              return writable.close();
            })
            .then(function () {
              // Сохраняем сам файл-хэндл как "последнее место".
              if (typeof global.saveLastMemoryDirectory === 'function') {
                return global.saveLastMemoryDirectory(handle);
              }
            });
        });
      })
      .then(function () {
        if (typeof global.hideSaveIndicator === 'function') global.hideSaveIndicator();
      }, function (err) {
        if (typeof global.hideSaveIndicator === 'function') global.hideSaveIndicator();
        throw err;
      });
  }

  /**
   * Загрузка данных из файла, выбранного пользователем (File System Access API).
   * Открывает диалог в последней выбранной папке (startIn), если она сохранена.
   *
   * @returns {Promise<Object>} - объект с загруженными данными (распарсенный JSON).
   */
  function load_all_memory() {
    if (!is_file_system_access_supported()) {
      alert_unsupported_browser();
      return Promise.reject(new Error('File System Access API не поддерживается.'));
    }

    var pickerOptions = {
      types: [{ description: 'JSON', accept: SAVE_ACCEPT }],
      multiple: false
    };

    var startInPromise = typeof global.loadLastMemoryDirectory === 'function'
      ? global.loadLastMemoryDirectory()
      : Promise.resolve(undefined);

    return startInPromise
      .then(function (startIn) {
        if (startIn) pickerOptions.startIn = startIn;
        return global.showOpenFilePicker(pickerOptions);
      })
      .then(function (handles) {
        if (!handles || handles.length === 0) {
          return Promise.reject(new Error('Файл не выбран.'));
        }
        var fileHandle = handles[0];
        if (typeof global.saveLastMemoryDirectory === 'function') {
          global.saveLastMemoryDirectory(fileHandle).catch(function () {});
        }
        return fileHandle.getFile();
      })
      .then(function (file) {
        return file.text();
      })
      .then(function (text) {
        try {
          return JSON.parse(text);
        } catch (e) {
          throw new Error('Файл не является корректным JSON: ' + e.message);
        }
      });
  }

  /**
   * Обработчик нажатия на кнопку «Сохранить память».
   *
   * @param {function(): Object} collectDataFn - функция, возвращающая объект для сохранения.
   * @returns {Promise<void>}
   */
  function handle_save_memory_click(collectDataFn) {
    if (!is_file_system_access_supported()) {
      alert_unsupported_browser();
      return Promise.reject(new Error('File System Access API не поддерживается.'));
    }

    var data;
    try {
      data = collectDataFn ? collectDataFn() : {};
    } catch (e) {
      if (typeof global.show_alert === 'function') {
        global.show_alert('Ошибка при сборе данных: ' + e.message, 0);
      }
      return Promise.reject(e);
    }

    if (typeof global.show_alert === 'function') {
      global.show_alert('Выберите место для сохранения файла памяти…', 2000);
    }

    return save_all_memory(data)
      .then(function () {
        if (typeof global.show_alert === 'function') {
          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);
        }
        throw error;
      });
  }

  // Экспорт в глобальное пространство имён
  global.save_all_memory = save_all_memory;
  global.load_all_memory = load_all_memory;
  global.handle_save_memory_click = handle_save_memory_click;
  global.is_file_system_access_supported = is_file_system_access_supported;

})(window);
