(function () {
  var ACMS = {};
  ACMS.Admin = {};
  ACMS.eventPool = [];
  // index.js が読み込み完了時に 'complete' へ更新する（document.readyState と同じ発想）。
  // ACMS.Ready はこのプロパティを見るだけなので、ACMS.events（index.js が生成する）を
  // import せずに済み、常にここ（acms.js、同期・ブロッキングで最初に実行される）に定義できる。
  ACMS.readyStates = {
    ready: 'loading',
    adminReady: 'loading',
  };

  /**
   *
   * @deprecated 新しいイベントシステムは `@ablogcms/events` を使用してください。
   * @param {string} name
   * @param {function} listener
   * @param {boolean|AddEventListenerOptions}
   */
  ACMS.addListener = function (name, listener, options = false) {
    document.addEventListener(name, listener, options);
    // dispatch from pool
    const events = ACMS.eventPool[name];
    if (events && events.length > 0) {
      events.forEach(function (item) {
        listener(item.event);
      });
    }
  };

  /**
   *
   * @deprecated 新しいイベントシステムは `@ablogcms/events` を使用してください。
   * @param {string} name
   * @param {HTMLElement} dom
   * @param {object} detail
   * @param {object} options
   */
  ACMS.dispatchEvent = function (name, dom = document, detail = {}, options = {}) {
    const event = new CustomEvent(name, {
      detail: detail,
      ...options,
      bubbles: true,
      cancelable: false,
    });
    event.obj = detail; // Ver.3.2.0以前との互換性を保つために追加
    dom.dispatchEvent(event);
    if (!ACMS.eventPool[name]) {
      ACMS.eventPool[name] = [];
    }
    ACMS.eventPool[name].push({
      event: event,
    });
  };

  /**
   * ACMS.Ready は、index.js が読み込み完了した後に発火するイベントを購読するための関数です。
   * index.js は、acms.js より後に読み込まれるため、acms.js から直接 ACMS.events を import することはできません。
   * そのため、ACMS.Ready は、index.js が読み込み完了した後に発火するイベントを購読するための関数として提供されています。
   * @param {function} listener
   */
  ACMS.Ready = function (listener) {
    if (ACMS.readyStates.ready === 'complete') {
      listener();
    } else if (ACMS.events) {
      ACMS.events.on('acms.state.ready', listener);
    } else {
      // ACMS.events はこの直後に読み込まれる index.js が生成するため、通常この分岐には
      // 入らない。ただし ACMS.Ready はテーマ・プラグインから任意のタイミングで呼ばれる
      // 公開 API のため、index.js より前に実行されるインラインスクリプト等からの
      // 呼び出しに備え、常に機能するレガシー機構（eventPool 再生）へフォールバックする。
      ACMS.addListener('acmsReady', listener);
    }
  };

  ACMS.ready = ACMS.Ready; // 今後はキャメルに統一するが、従来の ACMS.Ready も残す（互換性維持のため）。

  ACMS.adminReady = function (listener) {
    if (ACMS.readyStates.adminReady === 'complete') {
      listener();
    } else if (ACMS.events) {
      ACMS.events.on('acms.state.admin-ready', listener);
    } else {
      // ACMS.events はこの直後に読み込まれる index.js が生成するため、通常この分岐には
      // 入らない。ただし ACMS.adminReady はテーマ・プラグインから任意のタイミングで呼ばれる
      // 公開 API のため、index.js より前に実行されるインラインスクリプト等からの
      // 呼び出しに備え、常に機能するレガシー機構（eventPool 再生）へフォールバックする。
      ACMS.addListener('acmsAdminReady', listener);
    }
  };

  /**
   * ACMS.Loaded は、ページのロードが完了した後に発火するイベントを購読するための関数です。
   * これは、window.onload イベントと同等のタイミングで発火します。
   * @param {function} listener
   */
  ACMS.Loaded = function (listener) {
    if (document.readyState === 'complete') {
      listener();
    } else {
      window.addEventListener('load', listener);
    }
  };
  ACMS.loaded = ACMS.Loaded; // 今後はキャメルに統一するが、従来の ACMS.Loaded も残す（互換性維持のため）。
  window.ACMS = ACMS;
})();
