/**
 * @archivo progreso-control.js
 * /
importar componente desde '../../component.js';
importar * como Dom desde '../../utils/dom.js';
importar abrazadera desde '../../utils/clamp.js';
importar {bind, throttle, UPDATE_REFRESH_INTERVAL} desde '../../utils/fn.js';
importar {silencePromise} desde '../../utils/promise';

importar './buscar-bar.js';

/**
 * El componente Control de progreso contiene la barra de búsqueda, el progreso de carga,
 * y el progreso del juego.
 *
 * Componente @extiende
 * /
clase ProgressControl extiende Componente {

  /**
   * Crea una instancia de esta clase.
   *
   * @param {Jugador} jugador
   * El `Jugador` al que se debe adjuntar esta clase.
   *
   * @param {Objeto} [opciones]
   * El almacén de clave/valor de las opciones del jugador.
   * /
  constructor(jugador, opciones) {
    super(jugador, opciones);
    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);

    esto.habilitar();
  }

  /**
   * Crear el elemento DOM del 'Componente'
   *
   * @return {Elemento}
   * El elemento que se creó.
   * /
  crearEl() {
    return super.createEl('div', {
      className: 'vjs-progreso-control vjs-control'
    });
  }

  /**
   * Cuando el mouse se mueve sobre `ProgressControl`, la posición del puntero
   * pasa al componente `MouseTimeDisplay`.
   *
   * @param {EventTarget~Evento} evento
   * El evento `mousemove` que provocó la ejecución de esta función.
   *
   * @escuchar movimiento del ratón
   * /
  manejarMouseMove(evento) {
    const buscarBar = this.getChild('buscarBar');

    si (! barra de búsqueda) {
      devolver;
    }

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

    if (!playProgressBar && !mouseTimeDisplay) {
      devolver;
    }

    const buscarBarEl = buscarBar.el();
    const buscarBarRect = Dom.findPosition(buscarBarEl);
    let seekBarPoint = Dom.getPointerPosition(seekBarEl, event).x;

    // La máscara predeterminada tiene un espacio a cada lado de `SeekBar`. Esto significa
    // que es posible desencadenar este comportamiento fuera de los límites de
    // la `Barra de búsqueda`. Esto asegura que permanezcamos dentro de él en todo momento.
    buscarBarPoint = abrazadera(buscarBarPoint, 0, 1);

    si (mouseTimeDisplay) {
      mouseTimeDisplay.update(seekBarRect, seekBarPoint);
    }

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

  }

  /**
   * Una versión limitada del oyente {@link ProgressControl#handleMouseSeek}.
   *
   * @método ProgressControl#throttledHandleMouseSeek
   * @param {EventTarget~Evento} evento
   * El evento `mousemove` que provocó la ejecución de esta función.
   *
   * @escuchar movimiento del ratón
   * @escuchar tocar mover
   * /

  /**
   * Manejar eventos `mousemove` o `touchmove` en `ProgressControl`.
   *
   * @param {EventTarget~Evento} evento
   * Evento `mousedown` o `touchstart` que activó esta función
   *
   * @escucha movimiento del ratón
   * @escucha tocar mover
   * /
  handleMouseSeek(evento) {
    const buscarBar = this.getChild('buscarBar');

    si (barra de búsqueda) {
      seekBar.handleMouseMove(evento);
    }
  }

  /**
   * Los controles están habilitados actualmente para este control de progreso.
   *
   * @return {booleano}
   * verdadero si los controles están habilitados, falso de lo contrario
   * /
  activado() {
    devuelve esto.habilitado_;
  }

  /**
   * Deshabilitar todos los controles en el control de progreso y sus hijos
   * /
  desactivar() {
    this.children().forEach((hijo) => child.disable && niño.disable());

    si (! esto. habilitado ()) {
      devolver;
    }

    this.off(['mousedown', 'touchstart'], this.handleMouseDownHandler_);
    this.off(this.el_, 'movemouse', this.handleMouseMove);

    this.removeListenersAddedOnMousedownAndTouchstart();

    this.addClass('deshabilitado');

    esto.habilitado_ = falso;

    // Restaurar el estado de reproducción normal si los controles están deshabilitados durante la limpieza
    if (this.player_.scrubbing()) {
      const buscarBar = this.getChild('buscarBar');

      this.player_.scrubbing(falso);

      si (buscarBar.videoEstabaReproduciendo) {
        PromesaSilencio(este.jugador_.jugar());
      }
    }
  }

  /**
   * Habilite todos los controles en el control de progreso y sus hijos
   * /
  permitir() {
    this.children().forEach((hijo) => child.enable && niño.habilitar());

    si (esto.habilitado()) {
      devolver;
    }

    this.on(['mousedown', 'touchstart'], this.handleMouseDownHandler_);
    this.on(this.el_, 'movemouse', this.handleMouseMove);
    this.removeClass('deshabilitado');

    esto.habilitado_ = verdadero;
  }

  /**
   * Limpieza de oyentes después de que el usuario termine de interactuar con los controles de progreso
   * /
  removeListenersAddedOnMousedownAndTouchstart() {
    const doc = this.el_.ownerDocument;

    this.off(doc, 'movimiento del ratón', this.throttledHandleMouseSeek);
    this.off(doc, 'touchmove', this.throttledHandleMouseSeek);
    this.off(doc, 'mouseup', this.handleMouseUpHandler_);
    this.off(doc, 'touchend', this.handleMouseUpHandler_);
  }

  /**
   * Manejar eventos `mousedown` o `touchstart` en `ProgressControl`.
   *
   * @param {EventTarget~Evento} evento
   * Evento `mousedown` o `touchstart` que activó esta función
   *
   * @escucha mousedown
   * @escucha inicio táctil
   * /
  manejarRatónAbajo(evento) {
    const doc = this.el_.ownerDocument;
    const buscarBar = this.getChild('buscarBar');

    si (barra de búsqueda) {
      seekBar.handleMouseDown(evento);
    }

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

  /**
   * Manejar eventos `mouseup` o `touchend` en `ProgressControl`.
   *
   * @param {EventTarget~Evento} evento
   * Evento `mouseup` o `touchend` que activó esta función.
   *
   * @escucha tocar el extremo
   * @escucha mouseup
   * /
  manejarMouseUp(evento) {
    const buscarBar = this.getChild('buscarBar');

    si (barra de búsqueda) {
      seekBar.handleMouseUp(evento);
    }

    this.removeListenersAddedOnMousedownAndTouchstart();
  }
}

/**
 * Opciones predeterminadas para `ProgressControl`
 *
 * @type {Objeto}
 * @privado
 * /
ProgressControl.prototipo.opciones_ = {
  niños: [
    'barra de busqueda'
  ]
};

Componente.registerComponent('ProgressControl', ProgressControl);
exportar ProgressControl por defecto;