/**
 * @file 텍스트-트랙-디스플레이.js
 */
'../component'에서 컴포넌트 가져오기;
import * as Fn from '../utils/fn.js';
import * as Dom from '../utils/dom.js';
'글로벌/창'에서 창 가져오기;

const darkGray = '#222';
const lightGray = '#ccc';
const fontMap = {
  고정 폭: '단일 간격',
  sansSerif: '산세리프',
  serif: '세리프',
  monospaceSansSerif: '"안달레 모노", "루시다 콘솔", 모노스페이스',
  monospaceSerif: '"Courier New", 모노스페이스',
  ProportionalSansSerif: '산세리프',
  ProportionalSerif: '세리프',
  casual: '"Comic Sans MS", 임팩트, 판타지',
  script: '"모노타이프 코르시바", 필기체',
  smallcaps: '"Andale 모노", "Lucida Console", 모노스페이스, 산세리프'
};

/**
 * 주어진 16진수 색상 코드에서 rgba 색상을 구성합니다.
 *
 * @param {숫자} 색상
 * #f0e 또는 #f604e2와 같은 색상의 16진수.
 *
 * @param {숫자} 불투명도
 * 불투명도 값, 0.0 - 1.0.
 *
 * @return {문자열}
 * 'rgba(255, 0, 0, 0.3)'과 같이 생성된 rgba 색상입니다.
 */
내보내기 기능 constructColor(색상, 불투명도) {
  16 진수하자;

  if (색상 길이 === 4) {
    // 색상은 "#f0e"처럼 보입니다.
    hex = 색상[1] + 색상[1] + 색상[2] + 색상[2] + 색상[3] + 색상[3];
  } 그렇지 않으면 (color.length === 7) {
    // 색상은 "#f604e2"처럼 보입니다.
    hex = color.slice(1);
  } else {
    throw new Error('잘못된 색상 코드가 제공되었습니다. ' + color + '; #f0e 또는 #f604e2와 같은 형식이어야 합니다.');
  }
  리턴 'rgba(' +
    parseInt(hex.slice(0, 2), 16) + ',' +
    parseInt(hex.slice(2, 4), 16) + ',' +
    parseInt(hex.slice(4, 6), 16) + ',' +
    불투명도 + ')';
}

/**
 * DOM 요소의 스타일을 업데이트하십시오. 일부 스타일을 변경하면 오류가 발생합니다.
 * 특히 IE8에서. 그것들은 멍청해야합니다.
 *
 * @param {요소} 엘
 * 스타일을 지정할 DOM 요소입니다.
 *
 * @param {문자열} 스타일
 * 스타일을 지정해야 하는 요소의 CSS 속성입니다.
 *
 * @param {문자열} 규칙
 * 속성에 적용해야 하는 스타일 규칙입니다.
 *
 * @사적인
 */
function tryUpdateStyle(el, 스타일, 규칙) {
  {
    el.style[스타일] = 규칙;
  } 잡기 (e) {

    // 린터를 만족시킵니다.
    반품;
  }
}

/**
 * 텍스트 트랙 큐를 표시하기 위한 구성 요소입니다.
 *
 * @extends 컴포넌트
 */
클래스 TextTrackDisplay는 구성 요소 {를 확장합니다.

  /**
   * 이 클래스의 인스턴스를 만듭니다.
   *
   * @param {플레이어} 플레이어
   * 이 클래스가 연결되어야 하는 `Player`.
   *
   * @param {객체} [옵션]
   * 플레이어 옵션의 키/값 저장소.
   *
   * @param {Component~ReadyCallback} [준비]
   * `TextTrackDisplay`가 준비되었을 때 호출할 함수.
   */
  생성자(플레이어, 옵션, 준비) {
    super(플레이어, 옵션, 준비);

    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) {
        this.hide();
        반품;
      }

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

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

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

      에 대한 (하자 i = 0; i < 트랙.길이; i++) {
        this.player_.addRemoteTextTrack(tracks[i], true);
      }

      this.preselectTrack();
    }));
  }

  /**
  * 다음 우선순위에 따라 트랙을 미리 선택합니다.
  * - 이전에 선택한 {@link TextTrack}의 언어 및 종류와 일치
  * - 이전에 선택한 {@link TextTrack}의 언어만 일치
  * - 첫 번째 기본 캡션 트랙입니다.
  * - 첫 번째 기본 설명 트랙입니다.
  *
  * @listens Player#loadstart
  */
  preselectTrack() {
    const 모드 = {캡션: 1, 자막: 1};
    const trackList = this.player_.textTracks();
    const userPref = this.player_.cache_.selectedLanguage;
    let firstDesc;
    let firstCaptions;
    선호 추적하자;

    에 대한 (하자 i = 0; i < trackList.length; i++) {
      const track = trackList[i];

      만약에 (
        userPref && userPref.활성화 &&
        userPref.언어 && userPref.언어 === 트랙.언어 &&
        모드의 track.kind
      ) {
        // 항상 언어와 종류가 모두 일치하는 트랙을 선택합니다.
        if (track.kind === userPref.kind) {
          선호트랙 = 트랙;
        // 또는 언어와 일치하는 첫 번째 트랙을 선택합니다.
        } 그렇지 않으면 (!preferredTrack) {
          선호트랙 = 트랙;
        }

      // offTextTrackMenuItem을 클릭한 경우 모든 항목을 지웁니다.
      } 그렇지 않으면 (userPref && !userPref.활성화) {
        선호트랙 = null;
        firstDesc = null;
        firstCaptions = null;

      } 그렇지 않으면 (track.default) {
        if (track.kind === '설명' && !firstDesc) {
          firstDesc = 트랙;
        } else if (모드에서 track.kind && !firstCaptions) {
          firstCaptions = 트랙;
        }
      }
    }

    // preferredTrack은 사용자 기본 설정과 일치하고
    // 다른 모든 트랙보다 우선합니다.
    // 따라서 첫 번째 기본 트랙 앞에 preferredTrack을 표시합니다.
    // 설명 트랙 이전에 자막/캡션 트랙
    if (preferredTrack) {
      PreferredTrack.mode = '보여주기';
    } 그렇지 않으면 (firstCaptions) {
      firstCaptions.mode = '보여주기';
    } 그렇지 않으면 (firstDesc) {
      firstDesc.mode = '보여주기';
    }
  }

  /**
   * {@link TextTrack}의 표시를 현재 상태에서 다른 상태로 전환합니다.
   * 두 가지 상태만 있습니다.
   * - '보여진'
   * - '숨김'
   *
   * @listens Player#loadstart
   */
  토글디스플레이() {
    if (this.player_.tech_ && this.player_.tech_.featuresNativeTextTracks) {
      this.hide();
    } else {
      this.show();
    }
  }

  /**
   * {@link Component}의 DOM 요소를 생성합니다.
   *
   * @return {요소}
   * 생성된 요소입니다.
   */
  createEl() {
    return super.createEl('div', {
      className: 'vjs-텍스트-트랙-디스플레이'
    }, {
      '번역하다': '예',
      'aria-live': '끄기',
      'aria-atomic': '참'
    });
  }

  /**
   * 표시된 모든 {@link TextTrack}을 지웁니다.
   */
  클리어디스플레이() {
    if (typeof window.WebVTT === '함수') {
      window.WebVTT.processCues(window, [], this.el_);
    }
  }

  /**
   * {@link Player#texttrackchange} 또는
   * {@link Player#fullscreenchange}가 실행됩니다.
   *
   * @listens Player#texttrackchange
   * @listens Player#fullscreenchange
   */
  업데이트디스플레이() {
    const 트랙 = this.player_.textTracks();
    const allowMultipleShowingTracks = this.options_.allowMultipleShowingTracks;

    this.clearDisplay();

    if (allowMultipleShowingTracks) {
      const 보여주는 트랙 = [];

      에 대한 (하자 i = 0; i < 트랙.길이; ++i) {
        const 트랙 = 트랙[i];

        if (track.mode !== '표시') {
          계속하다;
        }
        보여주는Tracks.push(트랙);
      }
      this.updateForTrack(showingTracks);
      반품;
    }

    // 트랙 표시 우선 순위 모델: 여러 트랙이 '표시'되는 경우,
    // 'showing'인 첫 번째 '자막' 또는 '자막' 트랙 표시,
    // 그렇지 않으면 'showing'인 첫 번째 'descriptions' 트랙을 표시합니다.

    let descriptionsTrack = null;
    let captionsSubtitlesTrack = null;
    let i = 트랙 길이;

    동안 (i--) {
      const 트랙 = 트랙[i];

      if (track.mode === '표시') {
        if (track.kind === '설명') {
          descriptionsTrack = 트랙;
        } else {
          captionsSubtitlesTrack = 트랙;
        }
      }
    }

    if (captionsSubtitlesTrack) {
      if (this.getAttribute('aria-live') !== 'off') {
        this.setAttribute('aria-live', 'off');
      }
      this.updateForTrack(captionsSubtitlesTrack);
    } 그렇지 않으면 (descriptionsTrack) {
      if (this.getAttribute('aria-live') !== '주장') {
        this.setAttribute('aria-live', 'assertive');
      }
      this.updateForTrack(descriptionsTrack);
    }
  }

  /**
   * {@Link TextTrackSettings}에 따라 {@Link TextTrack} activeCue의 스타일을 지정합니다.
   *
   * @param {TextTrack} 트랙
   * 스타일에 대한 활성 신호를 포함하는 텍스트 트랙 개체.
   */
  updateDisplayState(트랙) {
    const overrides = this.player_.textTrackSettings.getValues();
    const 큐 = track.activeCues;

    i = cues.length;

    동안 (i--) {
      const 큐 = 큐[i];

      if (!cue) {
        계속하다;
      }

      const cueDiv = cue.displayState;

      if (overrides.color) {
        cueDiv.firstChild.style.color = overrides.color;
      }
      if (overrides.textOpacity) {
        tryUpdateStyle(
          cueDiv.firstChild,
          '색상',
          구성 색상(
            overrides.color || '#fff',
            overrides.textOpacity
          )
        );
      }
      if (overrides.backgroundColor) {
        cueDiv.firstChild.style.backgroundColor = overrides.backgroundColor;
      }
      if (overrides.backgroundOpacity) {
        tryUpdateStyle(
          cueDiv.firstChild,
          '배경색',
          구성 색상(
            overrides.backgroundColor || '#000',
            overrides.backgroundOpacity
          )
        );
      }
      if (overrides.windowColor) {
        if (overrides.windowOpacity) {
          tryUpdateStyle(
            큐디브,
            '배경색',
            구성 색상(overrides.windowColor, overrides.windowOpacity)
          );
        } else {
          cueDiv.style.backgroundColor = overrides.windowColor;
        }
      }
      if (overrides.edgeStyle) {
        if (overrides.edgeStyle === 'dropshadow') {
          cueDiv.firstChild.style.textShadow = `2px 2px 3px ${darkGray}, 2px 2px 4px ${darkGray}, 2px 2px 5px ${darkGray}`;
        } 그렇지 않으면 (overrides.edgeStyle === '올림') {
          cueDiv.firstChild.style.textShadow = `1px 1px ${darkGray}, 2px 2px ${darkGray}, 3px 3px ${darkGray}`;
        } 그렇지 않으면 (overrides.edgeStyle === '우울함') {
          cueDiv.firstChild.style.textShadow = `1px 1px ${lightGray}, 0 1px ${lightGray}, -1px -1px ${darkGray}, 0 -1px ${darkGray}`;
        } 그렇지 않으면 (overrides.edgeStyle === 'uniform') {
          cueDiv.firstChild.style.textShadow = `0 0 4px ${darkGray}, 0 0 4px ${darkGray}, 0 0 4px ${darkGray}, 0 0 4px ${darkGray}`;
        }
      }
      if (overrides.fontPercent && overrides.fontPercent !== 1) {
        const fontSize = window.parseFloat(cueDiv.style.fontSize);

        cueDiv.style.fontSize = (fontSize * overrides.fontPercent) + 'px';
        cueDiv.style.height = '자동';
        cueDiv.style.top = '자동';
      }
      if (overrides.fontFamily && overrides.fontFamily !== '기본값') {
        if (overrides.fontFamily === '작은 대문자') {
          cueDiv.firstChild.style.fontVariant = '작은 대문자';
        } else {
          cueDiv.firstChild.style.fontFamily = fontMap[overrides.fontFamily];
        }
      }
    }
  }

  /**
   * {@link Tech}의 {@link TextTrackList}에 {@link TextTrack}을 추가합니다.
   *
   * @param {TextTrack|TextTrack[]} 트랙
   * 목록에 추가할 텍스트 트랙 개체 또는 텍스트 트랙 배열.
   */
  updateForTrack(트랙) {
    if (!Array.isArray(트랙)) {
      트랙 = [트랙];
    }
    if (window.WebVTT 유형 !== '함수' ||
      tracks.every((트랙)=> {
        return !track.activeCues;
      })) {
      반품;
    }

    const 큐 = [];

    // 모든 활성 트랙 큐를 푸시합니다.
    에 대한 (하자 i = 0; i < 트랙.길이; ++i) {
      const 트랙 = 트랙[i];

      에 대한 (하자 j = 0; j < track.activeCues.length; ++j) {
        cues.push(track.activeCues[j]);
      }
    }

    // 새로운 큐를 처리하기 전에 모든 큐를 제거합니다.
    window.WebVTT.processCues(window, cues, this.el_);

    // 각 언어 텍스트 트랙에 고유한 클래스를 추가합니다. & 필요한 경우 설정 스타일 추가
    에 대한 (하자 i = 0; i < 트랙.길이; ++i) {
      const 트랙 = 트랙[i];

      에 대한 (하자 j = 0; j < track.activeCues.length; ++j) {
        const cueEl = track.activeCues[j].displayState;

        Dom.addClass(cueEl, 'vjs-text-track-cue');
        Dom.addClass(cueEl, 'vjs-text-track-cue-' + ((track.language) ? track.language : i));
        if (트랙.언어) {
          Dom.setAttribute(cueEl, 'lang', track.language);
        }
      }
      if (this.player_.textTrackSettings) {
        this.updateDisplayState(트랙);
      }
    }
  }

}

Component.registerComponent('TextTrackDisplay', TextTrackDisplay);
기본 TextTrackDisplay 내보내기;