/**
 * @file text-track-display.js
 * /
importar componente desde '../componente';
importar * como Fn desde '../utils/fn.js';
importar * como Dom desde '../utils/dom.js';
importar ventana desde 'global/window';

const grisoscuro = '#222';
const gris claro = '#ccc';
const fontMap = {
  monoespaciado: 'monoespaciado',
  sansserif: 'sans-serif',
  serif: 'serif',
  monospaceSansSerif: '"Andale Mono", "Lucida Console", monospace',
  monospaceSerif: '"Courier New", monospace',
  proporcionalSansSerif: 'sans-serif',
  proporcionalSerif: 'serif',
  casual: '"Comic Sans MS", Impacto, fantasía',
  escritura: '"Monotype Corsiva", cursiva',
  versalitas: '"Andale Mono", "Lucida Console", monoespacio, sans-serif'
};

/**
 * Construya un color rgba a partir de un código de color hexadecimal dado.
 *
 * @param {número} color
 * Número hexadecimal para el color, como #f0e o #f604e2.
 *
 * @param {número} opacidad
 * Valor de opacidad, 0.0 - 1.0.
 *
 * @return {cadena}
 * El color rgba que se creó, como 'rgba(255, 0, 0, 0.3)'.
 * /
función de exportación constructColor(color, opacidad) {
  dejar maleficio;

  if (color.longitud === 4) {
    // el color se parece a "#f0e"
    hexadecimal = color[1] + color[1] + color[2] + color[2] + color[3] + color[3];
  } else if (color.longitud === 7) {
    // el color se parece a "#f604e2"
    hexadecimal = color.rebanada(1);
  } else {
    throw new Error('Código de color proporcionado no válido, ' + color + '; debe formatearse como, por ejemplo, #f0e o #f604e2.');
  }
  devuelve 'rgba(' +
    parseInt(hexadecimal.segmento(0, 2), 16) + ',' +
    parseInt(hexadecimal.segmento(2, 4), 16) + ',' +
    parseInt(hexadecimal.segmento(4, 6), 16) + ',' +
    opacidad + ')';
}

/**
 * Intente actualizar el estilo de un elemento DOM. Algunos cambios de estilo arrojarán un error,
 * particularmente en IE8. Deberían ser noops.
 *
 * @param {Elemento} el
 * El elemento DOM al que se le aplicará estilo.
 *
 * @param {cadena} estilo
 * La propiedad CSS del elemento al que se debe aplicar estilo.
 *
 * regla @param {cadena}
 * La regla de estilo que se debe aplicar a la propiedad.
 *
 * @privado
 * /
function probarActualizarEstilo(el, estilo, regla) {
  intentar {
    el.style[estilo] = regla;
  } catch (e) {

    // Satisface linter.
    devolver;
  }
}

/**
 * El componente para mostrar señales de pista de texto.
 *
 * Componente @extiende
 * /
clase TextTrackDisplay 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.
   *
   * @param {Componente~ReadyCallback} [listo]
   * La función para llamar cuando `TextTrackDisplay` está listo.
   * /
  constructor(jugador, opciones, listo) {
    super(jugador, opciones, listo);

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

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

    // Esto solía llamarse durante el inicio del jugador, pero estaba causando un error
    // si una pista debe mostrarse de forma predeterminada y la pantalla aún no se ha cargado.
    // Probablemente debería moverse a un cargador de pistas externo cuando admitamos
    // pistas que no necesitan visualización.
    player.ready(Fn.bind(this, function() {
      si (jugador.tech_ && player.tech_.featuresNativeTextTracks) {
        esto. ocultar ();
        devolver;
      }

      player.on('cambio de pantalla completa', updateDisplayHandler);
      player.on('redimensionarjugador', actualizarDisplayHandler);

      window.addEventListener('cambio de orientación', updateDisplayHandler);
      jugador.on('disponer', () => window.removeEventListener('cambio de orientación', updateDisplayHandler));

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

      para (sea i = 0; i < pistas.longitud; i++) {
        this.player_.addRemoteTextTrack(pistas[i], verdadero);
      }

      this.preselectTrack();
    }));
  }

  /**
  * Preseleccione una pista siguiendo esta precedencia:
  *: coincide con el idioma y el tipo del {@link TextTrack} seleccionado previamente
  *: coincide solo con el idioma del {@link TextTrack} seleccionado anteriormente
  * - es la primera pista de subtítulos predeterminada
  * - es la primera pista de descripciones predeterminada
  *
  * @escucha Player#loadstart
  * /
  preseleccionar pista() {
    modos const = {subtítulos: 1, subtítulos: 1};
    const trackList = this.player_.textTracks();
    const userPref = this.player_.cache_.selectedLanguage;
    let firstDesc;
    let firstCaptions;
    let PreferredTrack;

    para (sea i = 0; i < trackList.longitud; i++) {
      const pista = trackList[i];

      si (
        usuarioPref && userPref.habilitado &&
        pref.usuario.idioma && userPref.idioma === pista.idioma &&
        track.kind en modos
      ) {
        // Elija siempre la pista que coincida con el idioma y el tipo
        if (pista.tipo === userPref.tipo) {
          pista preferida = pista;
        // o elige la primera pista que coincida con el idioma
        } más si (! pista preferida) {
          pista preferida = pista;
        }

      // borrar todo si se hizo clic en offTextTrackMenuItem
      } más si (usuarioPref && !usuarioPref.habilitado) {
        pistapreferida = null;
        primerDesc = nulo;
        primeros subtítulos = nulo;

      } más si (pista.predeterminado) {
        if (pista.tipo === 'descripciones' && !primerDesc) {
          primerDesc = pista;
        } else if (pista.tipo en modos && !primeros subtítulos) {
          primeros subtítulos = pista;
        }
      }
    }

    // La pista preferida coincide con la preferencia del usuario y toma
    // precedencia sobre todas las demás pistas.
    // Entonces, muestra la pista preferida antes de la primera pista predeterminada
    // y la pista de subtítulos/títulos antes de la pista de descripciones
    if (pista preferida) {
      preferidoTrack.mode = 'mostrando';
    } else if (primeros subtítulos) {
      firstCaptions.mode = 'mostrando';
    } más si (primerDesc) {
      firstDesc.mode = 'mostrando';
    }
  }

  /**
   * Cambia la visualización de {@link TextTrack} del estado actual al otro estado.
   * Solo hay dos estados:
   * - 'mostrado'
   * - 'oculto'
   *
   * @escucha Player#loadstart
   * /
  alternar pantalla () {
    si (this.player_.tech_ && this.player_.tech_.featuresNativeTextTracks) {
      esto. ocultar ();
    } else {
      este espectáculo();
    }
  }

  /**
   * Cree el elemento DOM del {@link Component}.
   *
   * @return {Elemento}
   * El elemento que se creó.
   * /
  crearEl() {
    return super.createEl('div', {
      className: 'vjs-text-track-display'
    }, {
      'traducir': 'sí',
      'aria-en vivo': 'apagado',
      'aria-atomic': 'verdadero'
    });
  }

  /**
   * Borrar todos los {@link TextTrack} mostrados.
   * /
  borrar pantalla () {
    if (tipo de ventana.WebVTT === 'función') {
      ventana.WebVTT.processCues(ventana, [], this.el_);
    }
  }

  /**
   * Actualizar el TextTrack mostrado cuando un {@link Player#texttrackchange} o
   * se dispara un {@link Player#fullscreenchange}.
   *
   * @escucha Player#texttrackchange
   * @escucha jugador#cambio de pantalla completa
   * /
  actualizarPantalla() {
    const pistas = this.player_.textTracks();
    const allowMultipleShowingTracks = this.options_.allowMultipleShowingTracks;

    this.clearDisplay();

    if (permitir Múltiples Mostrar Pistas) {
      const mostrandoTracks = [];

      para (sea i = 0; i < pistas.longitud; ++ yo) {
        const pista = pistas[i];

        if (track.mode !== 'mostrando') {
          continuar;
        }
        mostrandoTracks.push(pista);
      }
      this.updateForTrack(mostrandoTracks);
      devolver;
    }

    // Modelo de priorización de visualización de pistas: si se 'muestran' varias pistas,
    // muestra la primera pista de 'subtítulos' o 'captions' que está 'mostrando',
    // de lo contrario, muestra la primera pista de 'descripciones' que está 'mostrando'

    let descripcionesTrack = null;
    let captionsSubtitlesTrack = null;
    let i = pistas.longitud;

    mientras yo--) {
      const pista = pistas[i];

      if (track.mode === 'mostrando') {
        if (pista.tipo === 'descripciones') {
          descripcionesTrack = track;
        } else {
          captionsSubtitlesTrack = pista;
        }
      }
    }

    if (captionsSubtitlesTrack) {
      if (this.getAttribute('aria-live') !== 'off') {
        this.setAttribute('aria-live', 'off');
      }
      this.updateForTrack(captionsSubtitlesTrack);
    } else if (descripcionesPista) {
      if (this.getAttribute('aria-live') !== 'asertivo') {
        this.setAttribute('aria-live', 'asertivo');
      }
      this.updateForTrack(descriptionsTrack);
    }
  }

  /**
   * Estilo {@Link TextTrack} activeCues según {@Link TextTrackSettings}.
   *
   * @param {TextTrack} pista
   * Objeto de pista de texto que contiene señales activas para diseñar.
   * /
  actualizarDisplayState(pista) {
    const overrides = this.player_.textTrackSettings.getValues();
    const cues = track.activeCues;

    let i = cues.longitud;

    mientras yo--) {
      const señal = señal[i];

      si (! señal) {
        continuar;
      }

      const cueDiv = cue.displayState;

      if (anula.color) {
        cueDiv.firstChild.style.color = overrides.color;
      }
      if (anula.textOpacity) {
        intentarActualizarEstilo(
          cueDiv.primer hijo,
          'color',
          construirColor(
            anula.color || '#fff',
            overrides.textOpacity
          )
        );
      }
      if (anula.backgroundColor) {
        cueDiv.firstChild.style.backgroundColor = overrides.backgroundColor;
      }
      if (anula.backgroundOpacity) {
        intentarActualizarEstilo(
          cueDiv.primer hijo,
          'color de fondo',
          construirColor(
            overrides.backgroundColor || '#000',
            overrides.backgroundOpacity
          )
        );
      }
      if (anula.windowColor) {
        if (anula.windowOpacity) {
          intentarActualizarEstilo(
            cueDiv,
            'color de fondo',
            constructColor(overrides.windowColor, overrides.windowOpacity)
          );
        } else {
          cueDiv.style.backgroundColor = overrides.windowColor;
        }
      }
      if (anula.edgeStyle) {
        if (overrides.edgeStyle === 'sombra paralela') {
          cueDiv.firstChild.style.textShadow = `2px 2px 3px ${gris oscuro}, 2px 2px 4px ${gris oscuro}, 2px 2px 5px ${gris oscuro}`;
        } else if (overrides.edgeStyle === 'elevado') {
          cueDiv.firstChild.style.textShadow = `1px 1px ${darkGray}, 2px 2px ${darkGray}, 3px 3px ${darkGray}`;
        } else if (overrides.edgeStyle === 'deprimido') {
          cueDiv.firstChild.style.textShadow = `1px 1px ${lightGray}, 0 1px ${lightGray}, -1px -1px ${darkGray}, 0 -1px ${darkGray}`;
        } else if (overrides.edgeStyle === 'uniforme') {
          cueDiv.firstChild.style.textShadow = `0 0 4px ${darkGray}, 0 0 4px ${darkGray}, 0 0 4px ${darkGray}, 0 0 4px ${darkGray}`;
        }
      }
      if (anula.fontPercent && overrides.fontPercent !== 1) {
        const fontSize = window.parseFloat(cueDiv.style.fontSize);

        cueDiv.style.fontSize = (fontSize * overrides.fontPercent) + 'px';
        cueDiv.style.height = 'auto';
        cueDiv.style.top = 'auto';
      }
      si (anula.fontFamily && overrides.fontFamily !== 'predeterminado') {
        if (overrides.fontFamily === 'small-caps') {
          cueDiv.firstChild.style.fontVariant = 'small-caps';
        } else {
          cueDiv.firstChild.style.fontFamily = fontMap[overrides.fontFamily];
        }
      }
    }
  }

  /**
   * Agregue un {@link TextTrack} a la {@link Tech}s {@link TextTrackList}.
   *
   * @param {TextTrack|TextTrack[]} pistas
   * Objeto de pista de texto o matriz de pista de texto para agregar a la lista.
   * /
  updateForTrack(pistas) {
    if (!Array.isArray(pistas)) {
      pistas = [pistas];
    }
    if (tipo de ventana.WebVTT !== 'función' ||
      pistas.cada((pista)=> {
        return !track.activeCues;
      })) {
      devolver;
    }

    señales constantes = [];

    // empuja todas las señales de pista activas
    para (sea i = 0; i < pistas.longitud; ++ yo) {
      const pista = pistas[i];

      para (sea j = 0; j < track.activeCues.longitud; ++j) {
        cues.push(pista.activeCues[j]);
      }
    }

    // elimina todas las señales antes de procesar las nuevas
    ventana.WebVTT.processCues(ventana, señales, this.el_);

    // agrega una clase única a cada pista de texto de idioma & agregue estilo de configuración si es necesario
    para (sea i = 0; i < pistas.longitud; ++ yo) {
      const pista = pistas[i];

      para (sea j = 0; j < track.activeCues.longitud; ++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 (pista.idioma) {
          Dom.setAttribute(cueEl, 'lang', pista.idioma);
        }
      }
      if (this.player_.textTrackSettings) {
        this.updateDisplayState(pista);
      }
    }
  }

}

Component.registerComponent('TextTrackDisplay', TextTrackDisplay);
exportar TextTrackDisplay predeterminado;