/**
 * @file create-logger.js
 * @module 創建記錄器
 */
從“全局/窗口”導入窗口;

// 這是日誌記錄歷史的私有跟踪變量。
讓歷史= [];

/**
 *根據消息類型將消息記錄到控制台和歷史記錄
 *
 * @私人的
 * @param {string} 類型
 * 要使用的控制台方法的名稱。
 *
 * @param {數組} 參數
 * 要傳遞給匹配的控制台方法的參數。
 */
const LogByTypeFactory = (name, log) => (type, level, args) => {
  const lvl = log.levels[級別];
  const lvlRegExp = new RegExp(`^(${lvl})$`);

  如果(類型!=='日誌'){

    // 當類型不是“log”時,將類型添加到消息的前面。
    args.unshift(type.toUpperCase() + ':');
  }

  // 添加到歷史記錄後添加控制台前綴。
  args.unshift(名稱 + ':');

  // 此時將 args 的克隆添加到歷史記錄中。
  如果(歷史){
    history.push([].concat(args));

    // 只存儲 1000 個歷史條目
    const 拼接 = history.length - 1000;

    history.splice(0, splice > 0 ? splice :0);
  }

  // 如果沒有控制台,則不要嘗試輸出消息,但它們會
  // 仍然存儲在歷史中。
  如果(!window.console){
    返回;
  }

  // 在此函數之外設置一次,但包含它們
  // 在函數中可以更輕鬆地測試控制台不存在的用例
  // 當模塊被執行時。
  讓 fn = window.console[type];

  如果(!fn && 類型 === '調試'){
    // 某些瀏覽器不支持 console.debug。對於那些,我們
    // 應默認為最接近的可比較日誌。
    fn = window.console.info ||窗口.控制台.log;
  }

  // 如果沒有控制台或者如果此類型不被允許,則退出
  // 當前日誌記錄級別。
  如果(!fn || !lvl || !lvlRegExp.test(類型)){
    返回;
  }

  fn[Array.isArray(args) ? '申請':'呼叫'](window.console,args);
};

導出默認函數 createLogger(name) {
  // 這是日誌記錄級別的私有跟踪變量。
  讓水平='信息';

  // curried logByType 綁定到特定的日誌和歷史
  讓 logByType;

  /**
   * 記錄簡單的調試消息。類似於 `console.log`。
   *
   * 由於 [限制](https://github.com/jsdoc3/jsdoc/issues/955#issuecomment-313829149)
   * 我們的 JSDoc 模板,我們不能正確地將其記錄為一個函數
   * 和命名空間,因此其函數簽名記錄在此處。
   *
   * #### 參數
   * ##### *參數
   *混合[]
   *
   * 可以傳遞給 `console.log()` 的值的任意組合。
   *
   * #### 返回值
   *
   *`未定義`
   *
   * @命名空間
   * @param {混合 []} 參數
   * 應記錄的一條或多條消息或對象。
   */
  const log = function(...args) {
    logByType('日誌', 級別, args);
  };

  // 這是下面的日誌記錄方法使用的 logByType 助手
  logByType = LogByTypeFactory(名稱, 日誌);

  /**
   * 創建一個新的子記錄器,將舊名稱鏈接到新名稱。
   *
   * 例如,執行 `videojs.log.createLogger('player')` 然後使用該記錄器將記錄以下內容:
   *```js
   * mylogger('foo');
   * // > VIDEOJS: 播放器: foo
   *```
   *
   * @param {string} 名稱
   * 要添加的名稱調用新記錄器
   * @return {對象}
   */
  log.createLogger = (subname) => createLogger(name + ': ' + subname);

  /**
   * 可用日誌記錄級別的枚舉,其中鍵是級別名稱
   * 和值是包含允許的日誌記錄方法的`|`分隔的字符串
   * 在該日誌記錄級別。這些字符串用於創建正則表達式
   * 匹配被調用的函數名。
   *
   * Video.js 提供的級別是:
   *
   * - `關閉`:匹配沒有呼叫。任何可以轉換為 `false` 的值都將具有
   * 這個效果。限制最嚴。
   * - `全部`:僅匹配 Video.js 提供的函數(`debug`、`log`、
   * `log.warn` 和 `log.error`)。
   * - `調試`:匹配 `log.debug`、`log`、`log.warn` 和 `log.error` 調用。
   * - `info`(默認):匹配 `log`、`log.warn` 和 `log.error` 調用。
   * - `警告`:匹配 `log.warn` 和 `log.error` 調用。
   * - `錯誤`:僅匹配 `log.error` 調用。
   *
   * @type {對象}
   */
  log.levels = {
    全部:“調試|日誌|警告|錯誤”,
    離開: '',
    調試:“調試|日誌|警告|錯誤”,
    信息:'日誌|警告|錯誤',
    警告:'警告|錯誤',
    錯誤:“錯誤”,
    默認的水平
  };

  /**
   * 獲取或設置當前日誌級別。
   *
   * 如果提供了與 {@link module:log.levels} 中的鍵匹配的字符串,則執行
   * 作為二傳手。
   *
   * @param {字符串} [lvl]
   * 傳遞有效級別以設置新的日誌記錄級別。
   *
   * @return {字符串}
   * 當前的日誌記錄級別。
   */
  log.level = (lvl) => {
    如果(類型 lvl === '字符串'){
      如果(!log.levels.hasOwnProperty(lvl)){
        throw new Error(`"${lvl}" in not a valid log level`);
      }
      等級 = lvl;
    }
    回歸水平;
  };

  /**
   * 返回一個數組,其中包含已記錄到歷史記錄中的所有內容。
   *
   * 該數組是內部歷史記錄的淺表克隆。然而,其
   * 內容_not_ 克隆;所以,改變這個數組中的對象將
   *在歷史上改變他們。
   *
   * @return {數組}
   */
  log.history = () => 歷史 ? [].concat(歷史) : [];

  /**
   * 允許您按給定的記錄器名稱過濾歷史記錄
   *
   * @param {string} fname
   * 要過濾的名字
   *
   * @return {數組}
   * 返回過濾後的列表
   */
  log.history.filter = (fname) => {
    返回(歷史 || []).filter((historyItem)=> {
      // 如果每個 historyItem 中的第一個項目包含 `fname`,那麼它是一個匹配項
      返回新的 RegExp(`.*${fname}.*`).test(historyItem[0]);
    });
  };

  /**
   * 清除內部歷史記錄跟踪,但不阻止進一步的歷史記錄
   * 追踪。
   */
  log.history.clear = () => {
    如果(歷史){
      歷史.length = 0;
    }
  };

  /**
   * 如果當前已啟用,則禁用歷史記錄跟踪。
   */
  log.history.disable = () => {
    如果(歷史!== null){
      歷史.length = 0;
      歷史=空;
    }
  };

  /**
   * 如果當前禁用,則啟用歷史記錄跟踪。
   */
  log.history.enable = () => {
    如果(歷史=== null){
      歷史 = [];
    }
  };

  /**
   * 記錄錯誤信息。類似於 console.error 。
   *
   * @param {混合 []} 參數
   * 應記錄為錯誤的一條或多條消息或對象
   */
  log.error = (...args) => logByType('error', level, args);

  /**
   * 記錄警告信息。類似於 `console.warn`。
   *
   * @param {混合 []} 參數
   * 應記錄為警告的一條或多條消息或對象。
   */
  log.warn = (...args) => logByType('warn', level, args);

  /**
   * 記錄調試消息。類似於 `console.debug`,但也可以作為類似的
   * 如果 `console.debug` 不可用則記錄
   *
   * @param {混合 []} 參數
   * 應記錄為調試的一條或多條消息或對象。
   */
  log.debug = (...args) => logByType('debug', level, args);

  返回日誌;
}