/**
 * @archivo slider.js
 * /
importar componente desde '../component.js';
importar * como Dom desde '../utils/dom.js';
importar {asignar} desde '../utils/obj';
importar {IS_CHROME} desde '../utils/browser.js';
importar abrazadera desde '../utils/clamp.js';
importar código clave desde 'código clave';

/**
 * La funcionalidad base para un control deslizante. Puede ser vertical u horizontal.
 * Por ejemplo, la barra de volumen o la barra de búsqueda en un video es un control deslizante.
 *
 * Componente @extiende
 * /
El control deslizante de clase extiende el componente {

  /**
 * Crear 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.handleMouseDown_ = (e) => this.handleMouseDown(e);
    this.handleMouseUp_ = (e) => this.handleMouseUp(e);
    this.handleKeyDown_ = (e) => this.handleKeyDown(e);
    this.handleClick_ = (e) => this.handleClick(e);
    this.handleMouseMove_ = (e) => this.handleMouseMove(e);
    esta.actualización_ = (e) => esta.actualización(e);

    // Establece los nombres de las propiedades en la barra para que coincidan con la clase secundaria Slider que está buscando
    this.bar = this.getChild(this.options_.barName);

    // Establecer una clase horizontal o vertical en el control deslizante según el tipo de control deslizante
    this.vertical(!!this.options_.vertical);

    esto.habilitar();
  }

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

  /**
   * Habilite los controles para este control deslizante si están deshabilitados
   * /
  permitir() {
    si (esto.habilitado()) {
      devolver;
    }

    this.on('mousedown', this.handleMouseDown_);
    this.on('touchstart', this.handleMouseDown_);
    this.on('keydown', this.handleKeyDown_);
    this.on('clic', this.handleClick_);

    // TODO: en desuso, los controles visibles no parecen estar activados
    this.on(this.player_, 'controlsvisible', this.update);

    if (este.jugadorEvento) {
      this.on(this.player_, this.playerEvent, this.update);
    }

    this.removeClass('deshabilitado');
    este.setAttribute('tabindex', 0);

    esto.habilitado_ = verdadero;
  }

  /**
   * Deshabilitar los controles para este control deslizante si están habilitados
   * /
  desactivar() {
    si (! esto. habilitado ()) {
      devolver;
    }
    const doc = this.bar.el_.ownerDocument;

    this.off('mousedown', this.handleMouseDown_);
    this.off('touchstart', this.handleMouseDown_);
    this.off('keydown', this.handleKeyDown_);
    this.off('clic', this.handleClick_);
    this.off(this.player_, 'controlsvisible', this.update_);
    this.off(doc, 'movemouse', this.handleMouseMove_);
    this.off(doc, 'mouseup', this.handleMouseUp_);
    this.off(doc, 'touchmove', this.handleMouseMove_);
    this.off(doc, 'touchend', this.handleMouseUp_);
    this.removeAttribute('tabindex');

    this.addClass('deshabilitado');

    if (este.jugadorEvento) {
      this.off(this.player_, this.playerEvent, this.update);
    }
    esto.habilitado_ = falso;
  }

  /**
   * Crear el elemento DOM `Slider`s.
   *
   * @param {cadena} tipo
   * Tipo de elemento a crear.
   *
   * @param {Objeto} [props={}]
   * Lista de propiedades en forma de Objeto.
   *
   * @param {Objeto} [atributos={}]
   * lista de atributos en forma de objeto.
   *
   * @return {Elemento}
   * El elemento que se crea.
   * /
  createEl(tipo, accesorios = {}, atributos = {}) {
    // Agregue la clase de elemento deslizante a todas las subclases
    props.className = props.className + 'vjs-slider';
    accesorios = asignar ({
      índice de tabulación: 0
    }, props);

    atributos = asignar ({
      'rol': 'control deslizante',
      'aria-valuenow': 0,
      'aria-valuemin': 0,
      'aria-valuemax': 100,
      'índice de tabulación': 0
    }, attributes);

    return super.createEl(tipo, props, atributos);
  }

  /**
   * Manejar eventos `mousedown` o `touchstart` en el `Slider`.
   *
   * @param {EventTarget~Evento} evento
   * Evento `mousedown` o `touchstart` que activó esta función
   *
   * @escucha mousedown
   * @escucha inicio táctil
   * Deslizador de @fires#slideractive
   * /
  manejarRatónAbajo(evento) {
    const doc = this.bar.el_.ownerDocument;

    if (evento.tipo === 'mousedown') {
      event.preventDefault();
    }
    // No llamar a preventDefault() en touchstart en Chrome
    // para evitar las advertencias de la consola. Use un estilo de 'acción táctil: ninguno'
    // en su lugar, para evitar el desplazamiento involuntario.
    // https://developers.google.com/web/updates/2017/01/intervención-desplazamiento
    if (evento.tipo === 'touchstart' && !ES_CROMO) {
      event.preventDefault();
    }
    Dom.blockTextSelection();

    this.addClass('vjs-sliding');
    /**
     * Activado cuando el control deslizante está en un estado activo
     *
     * @event Slider#slideractive
     * @type {Objetivo del evento~Evento}
     * /
    this.trigger('control deslizante');

    this.on(doc, 'movemouse', this.handleMouseMove_);
    this.on(doc, 'mouseup', this.handleMouseUp_);
    this.on(doc, 'touchmove', this.handleMouseMove_);
    this.on(doc, 'touchend', this.handleMouseUp_);

    this.handleMouseMove(evento, verdadero);
  }

  /**
   * Maneje los eventos `mousemove`, `touchmove` y `mousedown` en este `Slider`.
   * Los eventos `mousemove` y `touchmove` solo activarán esta función durante
   * `mousedown` y `touchstart`. Esto se debe a {@link Slider#handleMouseDown} y
   * {@link Slider#handleMouseUp}.
   *
   * @param {EventTarget~Evento} evento
   * Evento `mousedown`, `mousemove`, `touchstart` o `touchmove` que activó
   * esta función
   * @param {boolean} mouseDown este es un indicador que debe establecerse en verdadero si `handleMouseMove` se llama directamente. Nos permite omitir cosas que no deberían suceder si vienen con el mouse hacia abajo, pero deberían suceder en el controlador de movimiento del mouse normal. El valor predeterminado es falso.
   *
   * @escucha movimiento del ratón
   * @escucha tocar mover
   * /
  manejarMouseMove(evento) {}

  /**
   * Manejar eventos `mouseup` o `touchend` en el `Slider`.
   *
   * @param {EventTarget~Evento} evento
   * Evento `mouseup` o `touchend` que activó esta función.
   *
   * @escucha tocar el extremo
   * @escucha mouseup
   * @fires Slider#sliderinactivo
   * /
  manejarMouseUp() {
    const doc = this.bar.el_.ownerDocument;

    Dom.unblockTextSelection();

    this.removeClass('vjs-sliding');
    /**
     * Se activa cuando el control deslizante ya no está en un estado activo.
     *
     * @event Slider#sliderinactivo
     * @type {Objetivo del evento~Evento}
     * /
    this.trigger('control deslizante inactivo');

    this.off(doc, 'movemouse', this.handleMouseMove_);
    this.off(doc, 'mouseup', this.handleMouseUp_);
    this.off(doc, 'touchmove', this.handleMouseMove_);
    this.off(doc, 'touchend', this.handleMouseUp_);

    esta.actualización();
  }

  /**
   * Actualiza la barra de progreso del `Slider`.
   *
   * @return {número}
   * El porcentaje de progreso que representa la barra de progreso como
   * número del 0 al 1.
   * /
  actualizar() {
    // En VolumeBar init tenemos un setTimeout para actualizar que aparece y actualiza
    // hasta el final de la pila de ejecución. El jugador es destruido antes de eso.
    // la actualización causará un error
    // Si no hay barra...
    if (!este.el_ || !este.bar) {
      devolver;
    }

    // sujetar el progreso entre 0 y 1
    // y solo redondeamos a cuatro decimales, como redondeamos a dos a continuación
    const progreso = this.getProgress();

    if (progreso === este.progreso_) {
      devolver el progreso;
    }

    este.progreso_ = progreso;

    this.requestNamedAnimationFrame('Slider#update', () => {
      // Establecer el nuevo ancho o alto de la barra
      const sizeKey = this.vertical() ? 'anchura altura';

      // Convierte a un porcentaje para el valor css
      this.bar.el().style[sizeKey] = (progreso * 100).toFixed(2) + '%';
    });

    devolver el progreso;
  }

  /**
   * Obtenga el porcentaje de la barra que debe llenarse
   * pero sujeta y redondeada.
   *
   * @return {número}
   * porcentaje lleno que el control deslizante es
   * /
  obtenerProgreso() {
    return Number(clamp(this.getPercent(), 0, 1).toFixed(4));
  }

  /**
   * Calcular la distancia para el control deslizante
   *
   * @param {EventTarget~Evento} evento
   * El evento que provocó la ejecución de esta función.
   *
   * @return {número}
   * La posición actual del control deslizante.
   * - position.x para `Slider`s verticales
   * - position.y para `Slider`s horizontales
   * /
  calcularDistancia(evento) {
    const position = Dom.getPointerPosition(this.el_, event);

    si (esto.vertical()) {
      posición de retorno.y;
    }
    posición de retorno.x;
  }

  /**
   * Manejar un evento `keydown` en el `Slider`. Relojes para izquierda, derecha, arriba y abajo.
   * teclas de flecha. Esta función solo se llamará cuando el control deslizante tenga el foco. Ver
   * {@link Slider#handleFocus} y {@link Slider#handleBlur}.
   *
   * @param {EventTarget~Evento} evento
   * el evento `keydown` que provocó la ejecución de esta función.
   *
   * @escucha tecla abajo
   * /
  handleKeyDown(evento) {

    // Flechas izquierda y abajo
    if (keycode.isEventKey(evento, 'Izquierda') || keycode.isEventKey(evento, 'Abajo')) {
      event.preventDefault();
      event.stopPropagation();
      esto.pasoAtrás();

    // Flechas arriba y derecha
    } else if (keycode.isEventKey(event, 'Right') || keycode.isEventKey(event, 'Up')) {
      event.preventDefault();
      event.stopPropagation();
      esto.pasoAdelante();
    } else {

      // Pasar el manejo de keydown para claves no compatibles
      super.handleKeyDown(evento);
    }
  }

  /**
   * Oyente para eventos de clic en el control deslizante, utilizado para evitar clics
   * desde burbujear hasta elementos principales como menús de botones.
   *
   * evento @param {Objeto}
   * Evento que provocó la ejecución de este objeto
   * /
  handleClick(evento) {
    event.stopPropagation();
    event.preventDefault();
  }

  /**
   * Obtener/establecer si el control deslizante es horizontal para vertical
   *
   * @param {booleano} [booleano]
   * - verdadero si el control deslizante es vertical,
   * - falso es horizontal
   *
   * @return {booleano}
   * - verdadero si el control deslizante es vertical y se obtiene
   * - falso si el control deslizante es horizontal y obtiene
   * /
  vertical(bool) {
    si (bool === indefinido) {
      devuelve esto.vertical_ || FALSO;
    }

    esto.vertical_ = !!bool;

    si (esto.vertical_) {
      this.addClass('vjs-slider-vertical');
    } else {
      this.addClass('vjs-slider-horizontal');
    }
  }
}

Component.registerComponent('Control deslizante', Control deslizante);
Exportar control deslizante predeterminado;