'use strict';
/*
 * LabRegistry — единый реестр симуляций лаборатории (контент-движок).
 *
 * Цель: симуляции описываются декларативным манифестом и сами себя регистрируют,
 * вместо захардкоженных массивов (SIMS), if-цепочек (openSim) и объектов (THEORY).
 *
 * Манифест:
 *   {
 *     id:       'pendulum',            // уникальный, без ':arg'
 *     cat:      'phys',                // math | phys | chem | bio | game
 *     title:    'Маятник',
 *     desc:     'Колебания, период…',
 *     preview:  string | function(),  // SVG-разметка карточки (функция вычисляется лениво)
 *     theory:   { title, sections[] },// объект для панели теории (как в THEORY)
 *     bodyId:   'sim-pendulum',        // (опц.) id тела; mount() — для ленивого создания DOM (Фаза 2)
 *     mount:    function(host){},      // (опц.) ленивое монтирование тела
 *     open:     function(ctx){},       // ctx = { id, arg } — открыть/инициализировать
 *     stop:     function(){},          // (опц.) остановить анимации (не разрушая)
 *     destroy:  function(){},          // (опц.) полностью закрыть; по умолчанию == stop
 *     subject, grade, topics           // (опц.) курикулумные поля (Фаза 5)
 *   }
 *
 * Загружается ПЕРВЫМ среди labs-скриптов, чтобы window.LabRegistry существовал
 * к моменту исполнения тел остальных модулей.
 */
(function () {
  var _list = [];   // манифесты в порядке регистрации
  var _byId = {};   // id -> манифест
  var _active = null; // текущая открытая симуляция

  function _baseId(id) {
    return id == null ? id : String(id).split(':')[0];
  }

  function register(m) {
    if (!m || !m.id) return null;
    if (Object.prototype.hasOwnProperty.call(_byId, m.id)) {
      // перерегистрация: заменить на месте, сохранив позицию
      for (var i = 0; i < _list.length; i++) {
        if (_list[i].id === m.id) { _list[i] = m; break; }
      }
    } else {
      _list.push(m);
    }
    _byId[m.id] = m;
    return m;
  }

  function get(id) {
    var b = _baseId(id);
    return Object.prototype.hasOwnProperty.call(_byId, b) ? _byId[b] : null;
  }

  function has(id) { return !!get(id); }

  function all() { return _list.slice(); }

  function setActive(m) { _active = m || null; }

  function stopActive() {
    if (_active && typeof _active.stop === 'function') {
      try { _active.stop(); } catch (e) { /* noop */ }
    }
  }

  function destroyActive() {
    if (_active) {
      if (typeof _active.destroy === 'function') {
        try { _active.destroy(); } catch (e) { /* noop */ }
      } else if (typeof _active.stop === 'function') {
        try { _active.stop(); } catch (e) { /* noop */ }
      }
    }
    _active = null;
  }

  function active() { return _active; }

  // Разрешить preview (строка или функция) в готовую разметку.
  function resolvePreview(m) {
    if (!m) return '';
    var p = m.preview;
    if (typeof p === 'function') {
      try { return p() || ''; } catch (e) { return ''; }
    }
    return p || '';
  }

  window.LabRegistry = {
    register: register,
    get: get,
    has: has,
    all: all,
    setActive: setActive,
    stopActive: stopActive,
    destroyActive: destroyActive,
    active: active,
    resolvePreview: resolvePreview
  };
})();
