/**
 * @file 진행 제어.js
 */
'../../component.js'에서 컴포넌트 가져오기;
import * as Dom from '../../utils/dom.js';
'../../utils/clamp.js'에서 클램프 가져오기;
import {bind, throttle, UPDATE_REFRESH_INTERVAL} from '../../utils/fn.js';
'../../utils/promise'에서 {silencePromise} 가져오기;

import './seek-bar.js';

/**
 * 진행률 제어 구성요소에는 검색 표시줄, 로드 진행률,
 * 및 재생 진행.
 *
 * @extends 컴포넌트
 */
클래스 ProgressControl 확장 구성 요소 {

  /**
   * 이 클래스의 인스턴스를 만듭니다.
   *
   * @param {플레이어} 플레이어
   * 이 클래스가 연결되어야 하는 `Player`.
   *
   * @param {객체} [옵션]
   * 플레이어 옵션의 키/값 저장소.
   */
  생성자(플레이어, 옵션) {
    super(플레이어, 옵션);
    this.handleMouseMove = throttle(bind(this, this.handleMouseMove), UPDATE_REFRESH_INTERVAL);
    this.throttledHandleMouseSeek = throttle(bind(this, this.handleMouseSeek), UPDATE_REFRESH_INTERVAL);
    this.handleMouseUpHandler_ = (e) => this.handleMouseUp(e);
    this.handleMouseDownHandler_ = (e) => this.handleMouseDown(e);

    this.enable();
  }

  /**
   * `Component`의 DOM 요소 생성
   *
   * @return {요소}
   * 생성된 요소입니다.
   */
  createEl() {
    return super.createEl('div', {
      className: 'vjs-진행 제어 vjs-제어'
    });
  }

  /**
   * 마우스가 `ProgressControl` 위로 이동하면 포인터 위치
   * `MouseTimeDisplay` 컴포넌트로 전달됩니다.
   *
   * @param {EventTarget~Event} 이벤트
   * 이 기능을 실행하게 만든 `mousemove` 이벤트.
   *
   * @listen 마우스무브
   */
  handleMouseMove(이벤트) {
    const seekBar = this.getChild('seekBar');

    if (!seekBar) {
      반품;
    }

    const playProgressBar = seekBar.getChild('playProgressBar');
    const mouseTimeDisplay = seekBar.getChild('mouseTimeDisplay');

    if (!playProgressBar && !mouseTimeDisplay) {
      반품;
    }

    const seekBarEl = seekBar.el();
    const seekBarRect = Dom.findPosition(seekBarEl);
    let seekBarPoint = Dom.getPointerPosition(seekBarEl, event).x;

    // 기본 스킨은 `SeekBar` 양쪽에 간격이 있습니다. 이것은 의미합니다
    // 경계 외부에서 이 동작을 트리거할 수 있습니다.
    // `SeekBar`. 이를 통해 우리는 항상 그 안에 머물 수 있습니다.
    seekBarPoint = 클램프(seekBarPoint, 0, 1);

    경우 (mouseTimeDisplay) {
      mouseTimeDisplay.update(seekBarRect, seekBarPoint);
    }

    경우 (playProgressBar) {
      playProgressBar.update(seekBarRect, seekBar.getProgress());
    }

  }

  /**
   * {@link ProgressControl#handleMouseSeek} 리스너의 제한된 버전입니다.
   *
   * @method ProgressControl#throttledHandleMouseSeek
   * @param {EventTarget~Event} 이벤트
   * 이 기능을 실행하게 만든 `mousemove` 이벤트.
   *
   * @listen 마우스무브
   * @listen 터치무브
   */

  /**
   * `ProgressControl`에서 `mousemove` 또는 `touchmove` 이벤트를 처리합니다.
   *
   * @param {EventTarget~Event} 이벤트
   * 이 기능을 트리거한 `mousedown` 또는 `touchstart` 이벤트
   *
   * @listens mousemove
   * @listens 터치무브
   */
  handleMouseSeek(이벤트) {
    const seekBar = this.getChild('seekBar');

    경우 (탐색 바) {
      seekBar.handleMouseMove(이벤트);
    }
  }

  /**
   * 현재 이 진행률 컨트롤에 대해 컨트롤이 활성화되어 있습니까?
   *
   * @return {부울}
   * 컨트롤이 활성화된 경우 true, 그렇지 않은 경우 false
   */
  활성화() {
    this.enabled_를 반환합니다.
  }

  /**
   * 진행률 컨트롤과 그 자식에 대한 모든 컨트롤 비활성화
   */
  장애를 입히다() {
    this.children().forEach((자식) => 아이.비활성화 && child.disable());

    if (!this.enabled()) {
      반품;
    }

    this.off(['마우스다운', '터치스타트'], this.handleMouseDownHandler_);
    this.off(this.el_, 'mousemove', this.handleMouseMove);

    this.removeListenersAddedOnMousedownAndTouchstart();

    this.addClass('비활성화됨');

    this.enabled_ = 거짓;

    // 스크러빙하는 동안 컨트롤이 비활성화되면 일반 재생 상태로 복원
    if (this.player_.scrubbing()) {
      const seekBar = this.getChild('seekBar');

      this.player_.scrubbing(false);

      if (seekBar.videoWasPlaying) {
        침묵 약속(this.player_.play());
      }
    }
  }

  /**
   * 진행률 컨트롤과 그 자식에 대한 모든 컨트롤을 활성화합니다.
   */
  할 수 있게 하다() {
    this.children().forEach((자식) => 아동.활성화 && child.enable());

    if (이.활성화()) {
      반품;
    }

    this.on(['mousedown', 'touchstart'], this.handleMouseDownHandler_);
    this.on(this.el_, 'mousemove', this.handleMouseMove);
    this.removeClass('비활성화됨');

    this.enabled_ = 참;
  }

  /**
   * 사용자가 진행 컨트롤과의 상호 작용을 마친 후 리스너 정리
   */
  removeListenersAddedOnMousedownAndTouchstart() {
    const doc = this.el_.ownerDocument;

    this.off(doc, 'mousemove', this.throttledHandleMouseSeek);
    this.off(doc, 'touchmove', this.throttledHandleMouseSeek);
    this.off(doc, 'mouseup', this.handleMouseUpHandler_);
    this.off(doc, 'touchend', this.handleMouseUpHandler_);
  }

  /**
   * `ProgressControl`에서 `mousedown` 또는 `touchstart` 이벤트를 처리합니다.
   *
   * @param {EventTarget~Event} 이벤트
   * 이 기능을 트리거한 `mousedown` 또는 `touchstart` 이벤트
   *
   * @listens mousedown
   * @listens 터치스타트
   */
  handleMouseDown(이벤트) {
    const doc = this.el_.ownerDocument;
    const seekBar = this.getChild('seekBar');

    경우 (탐색 바) {
      seekBar.handleMouseDown(event);
    }

    this.on(doc, 'mousemove', this.throttledHandleMouseSeek);
    this.on(doc, 'touchmove', this.throttledHandleMouseSeek);
    this.on(doc, 'mouseup', this.handleMouseUpHandler_);
    this.on(doc, 'touchend', this.handleMouseUpHandler_);
  }

  /**
   * `ProgressControl`에서 `mouseup` 또는 `touchend` 이벤트를 처리합니다.
   *
   * @param {EventTarget~Event} 이벤트
   * 이 기능을 트리거한 `mouseup` 또는 `touchend` 이벤트.
   *
   * @listens 터치엔드
   * @listens mouseup
   */
  handleMouseUp(이벤트) {
    const seekBar = this.getChild('seekBar');

    경우 (탐색 바) {
      seekBar.handleMouseUp(이벤트);
    }

    this.removeListenersAddedOnMousedownAndTouchstart();
  }
}

/**
 * `ProgressControl`의 기본 옵션
 *
 * @type {객체}
 * @사적인
 */
ProgressControl.prototype.options_ = {
  어린이들: [
    '탐색 바'
  ]
};

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