/**
 * @file text-track-display.js
 */
從 '../component' 導入組件;
從 '../utils/fn.js' 導入 * 作為 Fn;
import * as Dom from '../utils/dom.js';
從“全局/窗口”導入窗口;

const darkGray = '#222';
const lightGray = '#ccc';
常量 fontMap = {
  等寬:'等寬',
  sansSerif: 'sans-serif',
  襯線:'襯線',
  monospaceSansSerif: '"Andale Mono", "Lucida Console", monospace',
  monospaceSerif: '"Courier New", monospace',
  proportionalSansSerif: 'sans-serif',
  proportionalSerif: '襯線',
  casual: '"Comic Sans MS", Impact, fantasy',
  script: '"Monotype Corsiva", 草書',
  smallcaps: '"Andale Mono", "Lucida Console", monospace, sans-serif'
};

/**
 * 從給定的十六進制顏色代碼構建 rgba 顏色。
 *
 * @param {number} 顏色
 * 顏色的十六進制數,如#f0e 或#f604e2。
 *
 * @param {number} 不透明度
 * 不透明度值,0.0 - 1.0。
 *
 * @return {字符串}
 * 創建的 rgba 顏色,如 'rgba(255, 0, 0, 0.3)'。
 */
導出函數構造顏色(顏色,不透明度){
  讓十六進制;

  如果(顏色。長度=== 4){
    // 顏色看起來像“#f0e”
    十六進制=顏色[1] + 顏色[1] + 顏色[2] + 顏色[2] + 顏色[3] + 顏色[3];
  } else if (color.length === 7) {
    // 顏色看起來像“#f604e2”
    hex = color.slice(1);
  }其他{
    throw new Error('提供的顏色代碼無效,' + 顏色 + ';必須格式化為例如 #f0e 或 #f604e2。');
  }
  返回'rgba('+
    parseInt(hex.slice(0, 2), 16) + ',' +
    parseInt(hex.slice(2, 4), 16) + ',' +
    parseInt(hex.slice(4, 6), 16) + ',' +
    不透明度 + ')';
}

/**
 * 嘗試更新 DOM 元素的樣式。某些樣式更改會引發錯誤,
 * 特別是在 IE8 中。那些應該是空話。
 *
 * @param {元素} el
 * 要設置樣式的 DOM 元素。
 *
 * @param {string} 樣式
 * 應設置樣式的元素的 CSS 屬性。
 *
 * @param {string} 規則
 * 應用於屬性的樣式規則。
 *
 * @私人的
 */
函數 tryUpdateStyle(el, 樣式, 規則) {
  嘗試{
    el.style[樣式] = 規則;
  } 抓住 (e) {

    // 滿足 linter。
    返回;
  }
}

/**
 * 顯示文本軌道提示的組件。
 *
 * @extends 組件
 */
類 TextTrackDisplay 擴展組件 {

  /**
   * 創建此類的一個實例。
   *
   * @param {Player} 播放器
   * 此類應附加到的 `Player`。
   *
   * @param {對象} [選項]
   * 播放器選項的鍵/值存儲。
   *
   * @param {Component~ReadyCallback} [就緒]
   * `TextTrackDisplay` 就緒時調用的函數。
   */
  構造函數(播放器,選項,準備就緒){
    超級(播放器,選項,準備就緒);

    const updateDisplayHandler = (e) => this.updateDisplay(e);

    player.on('loadstart', (e) => this.toggleDisplay(e));
    player.on('texttrackchange', updateDisplayHandler);
    player.on('loadedmetadata', (e) => this.preselectTrack(e));

    // 這曾經在播放器初始化期間調用,但會導致錯誤
    // 如果軌道應該默認顯示並且顯示尚未加載。
    // 當我們支持時,可能應該移動到外部軌道加載器
    // 不需要顯示的軌道。
    player.ready(Fn.bind(this, function() {
      如果(player.tech_ && player.tech_.featuresNativeTextTracks){
        這個。隱藏();
        返回;
      }

      player.on('fullscreenchange', updateDisplayHandler);
      player.on('playerresize', updateDisplayHandler);

      window.addEventListener('orientationchange', updateDisplayHandler);
      player.on('dispose', () => window.removeEventListener('orientationchange', updateDisplayHandler));

      const tracks = this.options_.playerOptions.tracks || [];

      對於(讓我 = 0; 我 < 跟踪。長度; 我 ++){
        this.player_.addRemoteTextTrack(tracks[i], true);
      }

      這個.preselectTrack();
    }));
  }

  /**
  * 按照此優先順序預選曲目:
  * - 匹配先前選擇的 {@link TextTrack} 的語言和種類
  * - 僅匹配先前選擇的 {@link TextTrack} 的語言
  * - 是第一個默認字幕軌道
  * - 是第一個默認描述軌道
  *
  * @listens Player#loadstart
  */
  預選軌道(){
    const 模式 = {字幕:1、字幕:1};
    const trackList = this.player_.textTracks();
    const userPref = this.player_.cache_.selectedLanguage;
    讓 firstDesc;
    讓第一個字幕;
    讓首選軌道;

    對於(讓我 = 0; 我 < 跟踪列表長度; 我 ++){
      const track = trackList[i];

      如果 (
        userPref && userPref.enabled &&
        userPref.language && userPref.language === track.language &&
        track.kind 模式
      ) {
        // 始終選擇匹配語言和種類的曲目
        如果(track.kind === userPref.kind){
          首選軌道=軌道;
        // 或選擇匹配語言的第一首曲目
        } 否則,如果(!首選跟踪){
          首選軌道=軌道;
        }

      // 如果單擊了 offTextTrackMenuItem,則清除所有內容
      } 否則如果(用戶偏好 &&!使用者先決條件。啟用) {
        首選軌道=空;
        firstDesc = null;
        firstCaptions = null;

      } else if (track.default) {
        如果(跟踪一種 === '描述' &&!第一描述) {
          firstDesc = 跟踪;
        } 否則如果(跟踪模式 &&!第一字幕) {
          firstCaptions = 跟踪;
        }
      }
    }

    // preferredTrack 匹配用戶偏好並採用
    // 優先於所有其他軌道。
    // 因此,在第一個默認曲目之前顯示 preferredTrack
    // 和描述軌道之前的字幕軌道
    如果(首選軌道){
      preferredTrack.mode = '顯示';
    } else if (firstCaptions) {
      firstCaptions.mode = '顯示';
    } else if (firstDesc) {
      firstDesc.mode = '顯示';
    }
  }

  /**
   * 將 {@link TextTrack} 的顯示從當前狀態轉換為其他狀態。
   * 只有兩種狀態:
   * - '顯示'
   * - '隱藏'
   *
   * @listens Player#loadstart
   */
  切換顯示(){
    如果(this.player_.tech_ && this.player_.tech_.featuresNativeTextTracks){
      這個。隱藏();
    }其他{
      這個。顯示();
    }
  }

  /**
   * 創建 {@link Component} 的 DOM 元素。
   *
   * @return {元素}
   * 創建的元素。
   */
  創建El() {
    返回 super.createEl('div', {
      className: 'vjs-text-track-display'
    },{
      '翻譯':'是',
      'aria-live':'關閉',
      'aria-atomic':'真'
    });
  }

  /**
   * 清除所有顯示的 {@link TextTrack}。
   */
  清除顯示(){
    如果 (typeof window.WebVTT === '函數') {
      window.WebVTT.processCues(窗口,[],this.el_);
    }
  }

  /**
   * 當 {@link Player#texttrackchange} 或
   * {@link Player#fullscreenchange} 被觸發。
   *
   * @listens Player#texttrackchange
   * @listens Player#fullscreenchange
   */
  更新顯示(){
    const tracks = this.player_.textTracks();
    const allowMultipleShowingTracks = this.options_.allowMultipleShowingTracks;

    這個.clearDisplay();

    如果(allowMultipleShowingTracks){
      const showingTracks = [];

      為 (讓我 = 0; 我 < 跟踪. 長度; ++i) {
        const track = tracks[i];

        如果(跟踪模式!== '顯示'){
          繼續;
        }
        showingTracks.push(track);
      }
      this.updateForTrack(showingTracks);
      返回;
    }

    // 軌道顯示優先級模型:如果多個軌道正在“顯示”,
    // 顯示第一個 'subtitles' or 'captions' track which is 'showing',
    // 否則顯示第一個“正在顯示”的“描述”曲目

    讓 descriptionsTrack = null;
    讓 captionsSubtitlesTrack = null;
    設 i = tracks.length;

    當我 - ) {
      const track = tracks[i];

      如果(track.mode ==='顯示'){
        如果(track.kind ==='描述'){
          descriptionsTrack =跟踪;
        }其他{
          字幕字幕軌道 = 軌道;
        }
      }
    }

    如果(字幕字幕跟踪){
      如果(這個。獲取屬性('詠嘆調-活')!== '關閉'){
        this.setAttribute('aria-live', 'off');
      }
      this.updateForTrack(字幕字幕跟踪);
    } else if (descriptionsTrack) {
      如果(這個。獲取屬性('詠嘆調-活')!== '自信'){
        this.setAttribute('aria-live', 'assertive');
      }
      this.updateForTrack(描述跟踪);
    }
  }

  /**
   * 根據 {@Link TextTrackSettings} 設計 {@Link TextTrack} activeCues。
   *
   * @param {TextTrack} 軌道
   * 包含樣式活動提示的文本軌道對象。
   */
  更新顯示狀態(軌道){
    const overrides = this.player_.textTrackSettings.getValues();
    const cues = track.activeCues;

    讓我= cues.length;

    當我 - ) {
      const cue = 提示[i];

      如果(!提示){
        繼續;
      }

      const cueDiv = cue.displayState;

      如果(覆蓋顏色){
        cueDiv.firstChild.style.color = overrides.color;
      }
      如果(覆蓋。textOpacity){
        嘗試更新樣式(
          cueDiv.firstChild,
          '顏色',
          構造顏色(
            覆蓋顏色 || '#fff',
            覆蓋.textOpacity
          )
        );
      }
      如果(覆蓋。背景顏色){
        cueDiv.firstChild.style.backgroundColor = overrides.backgroundColor;
      }
      如果(覆蓋。backgroundOpacity){
        嘗試更新樣式(
          cueDiv.firstChild,
          '背景顏色',
          構造顏色(
            overrides.backgroundColor || '#000',
            overrides.backgroundOpacity
          )
        );
      }
      如果(覆蓋。windowColor){
        如果(覆蓋。windowOpacity){
          嘗試更新樣式(
            提示分區,
            '背景顏色',
            constructColor(overrides.windowColor,overrides.windowOpacity)
          );
        }其他{
          cueDiv.style.backgroundColor = overrides.windowColor;
        }
      }
      如果(覆蓋。edgeStyle){
        如果(overrides.edgeStyle === 'dropshadow'){
          文本陰影 = `2 像素 2 像素 3 像素 $ {暗灰色},2 像素 2 像素 4 像素 $ {暗灰色},2 像素 2 像素 5 像素 $ {深灰色} `;
        } else if (overrides.edgeStyle === 'raised') {
          文本陰影 = `1 像素 $ {暗灰色},2 像素 2 像素 $ {暗灰色},3 像素 3 像素 $ {暗灰色} `;
        } else if (overrides.edgeStyle === 'depressed') {
          cueDiv.firstChild.style.textShadow = `1px 1px ${lightGray}, 0 1px ${lightGray}, -1px -1px ${darkGray}, 0 -1px ${darkGray}`;
        } else if (overrides.edgeStyle === 'uniform') {
          cueDiv.firstChild.style.textShadow = `0 0 4px ${darkGray}, 0 0 4px ${darkGray}, 0 0 4px ${darkGray}, 0 0 4px ${darkGray}`;
        }
      }
      如果(覆蓋 .Font 百分比 && 覆蓋。字體百分比!1) {
        const fontSize = window.parseFloat(cueDiv.style.fontSize);

        cueDiv.style.fontSize = (fontSize * overrides.fontPercent) + 'px';
        cueDiv.style.height = '自動';
        cueDiv.style.top = '自動';
      }
      如果(覆蓋字體家庭 && 概述。字體家庭!== '默認'){
        if (overrides.fontFamily === 'small-caps') {
          cueDiv.firstChild.style.fontVariant = 'small-caps';
        }其他{
          cueDiv.firstChild.style.fontFamily = fontMap[overrides.fontFamily];
        }
      }
    }
  }

  /**
   * 將 {@link TextTrack} 添加到 {@link Tech} 的 {@link TextTrackList}。
   *
   * @param {TextTrack|TextTrack[]} 軌道
   * 要添加到列表中的文本軌道對像或文本軌道數組。
   */
  updateForTrack(曲目){
    如果(!Array.isArray(曲目)){
      曲目 = [曲目];
    }
    如果(窗口的類型。== '功能' ||
      tracks.every((track)=> {
        返回!track.activeCues;
      })) {
      返回;
    }

    const 線索 = [];

    // 推送所有活動軌道提示
    為 (讓我 = 0; 我 < 跟踪. 長度; ++i) {
      const track = tracks[i];

      為 (讓 j = 0;  <  j 軌道. 活動. 長度; ++j) {
        cues.push(track.activeCues[j]);
      }
    }

    // 在處理新線索之前刪除所有線索
    window.WebVTT.processCues(窗口,提示,this.el_);

    // 為每種語言文本軌道添加獨特的類,並在必要時添加設置樣式
    為 (讓我 = 0; 我 < 跟踪. 長度; ++i) {
      const track = tracks[i];

      為 (讓 j = 0;  <  j 軌道. 活動. 長度; ++j) {
        const cueEl = track.activeCues[j].displayState;

        Dom.addClass(cueEl, 'vjs-text-track-cue');
        添加類 (搜索, 'VJS-文本跟踪提示-' + ((軌道. 語言)?跟踪語言:i));
        如果(track.language){
          Dom.setAttribute(cueEl, 'lang', track.language);
        }
      }
      如果(this.player_.textTrackSettings){
        this.updateDisplayState(track);
      }
    }
  }

}

Component.registerComponent('TextTrackDisplay', TextTrackDisplay);
導出默認 TextTrackDisplay;