/**
 * @file text-track-settings.js
 * /
importar ventana desde 'global/window';
importar componente desde '../componente';
importar ModalDialog desde '../modal-dialog';
importar {createEl} desde '../utils/dom';
importar * como Obj desde '../utils/obj';
importar registro desde '../utils/log';

const LOCAL_STORAGE_KEY = 'vjs-text-track-settings';

const COLOR_NEGRO = ['#000', 'Negro'];
const COLOR_AZUL = ['#00F', 'Azul'];
const COLOR_CYAN = ['#0FF', 'Cyan'];
const COLOR_VERDE = ['#0F0', 'Verde'];
const COLOR_MAGENTA = ['#F0F', 'Magenta'];
const COLOR_RED = ['#F00', 'Rojo'];
const COLOR_BLANCO = ['#FFF', 'Blanco'];
const COLOR_AMARILLO = ['#FF0', 'Amarillo'];

const OPACIDAD_OPAQUE = ['1', 'Opaque'];
const OPACITY_SEMI = ['0.5', 'Semi-Transparente'];
const OPACIDAD_TRANS = ['0', 'Transparente'];

// Configuración para los distintos < seleccionar> elementos en el DOM de este componente.
//
// Las claves posibles incluyen:
//
// `predeterminado`:
// El índice de opciones predeterminado. Solo debe proporcionarse si no es cero.
// `analizador`:
// Una función que se utiliza para analizar el valor de la opción seleccionada en
// una forma personalizada.
// `selector`:
// El selector usado para encontrar el asociado < seleccionar> elemento.
const seleccionarConfiguraciones = {
  color de fondo: {
    selector: '.vjs-bg-color > seleccionar',
    id: 'captions-background-color-%s',
    etiqueta: 'Color',
    opciones: [
      DE COLOR NEGRO,
      COLOR BLANCO,
      COLOR ROJO,
      COLOR VERDE,
      COLOR AZUL,
      COLOR AMARILLO,
      COLOR_MAGENTA,
      COLOR_CYAN
    ]
  },

  opacidad de fondo: {
    selector: '.vjs-bg-opacidad > seleccionar',
    id: 'subtítulos-fondo-opacidad-%s',
    etiqueta: 'Transparencia',
    opciones: [
      OPACIDAD_OPACO,
      OPACIDAD_SEMI,
      OPACIDAD_TRANS
    ]
  },

  color: {
    selector: '.vjs-fg-color > seleccionar',
    id: 'subtítulos-color de primer plano-%s',
    etiqueta: 'Color',
    opciones: [
      COLOR BLANCO,
      DE COLOR NEGRO,
      COLOR ROJO,
      COLOR VERDE,
      COLOR AZUL,
      COLOR AMARILLO,
      COLOR_MAGENTA,
      COLOR_CYAN
    ]
  },

  estilo de borde: {
    selector: '.vjs-estilo-de-borde > seleccionar',
    identificación: '%s',
    etiqueta: 'Estilo de borde de texto',
    opciones: [
      ['ninguno Ninguno'],
      ['criado', 'criado'],
      ['deprimido', 'deprimido'],
      ['uniforme', 'Uniforme'],
      ['sombra paralela', 'sombra paralela']
    ]
  },

  Familia tipográfica: {
    selector: '.vjs-font-familia > seleccionar',
    id: 'captions-font-family-%s',
    etiqueta: 'Familia tipográfica',
    opciones: [
      ['sans-serif proporcional', 'sans-serif proporcional'],
      ['monospaceSansSerif', 'Monospace Sans-Serif'],
      ['Serif proporcional', 'Serif proporcional'],
      ['monospace Serif', 'Monospace Serif'],
      ['casual', 'casual'],
      ['guion', 'guion'],
      ['small-caps', 'Small-Caps']
    ]
  },

  porcentaje de fuente: {
    selector: '.vjs-fuente-porcentaje > seleccionar',
    id: 'subtítulos-tamaño-de-fuente-%s',
    etiqueta: 'Tamaño de fuente',
    opciones: [
      ['0.50', '50%'],
      ['0.75', '75%'],
      ['1.00', '100%'],
      ['1.25', '125%'],
      ['1.50', '150%'],
      ['1.75', '175%'],
      ['2.00', '200%'],
      ['3.00', '300%'],
      ['4.00', '400%']
    ],
    por defecto: 2,
    analizador: (v) => === '1.00' ? nulo : Número (v)
  },

  opacidad del texto: {
    selector: '.vjs-texto-opacidad > seleccionar',
    id: 'subtítulos-primer plano-opacidad-%s',
    etiqueta: 'Transparencia',
    opciones: [
      OPACIDAD_OPACO,
      OPACIDAD_SEMI
    ]
  },

  // Las opciones para este objeto se definen a continuación.
  color de la ventana: {
    selector: '.vjs-ventana-color > seleccionar',
    id: 'captions-window-color-%s',
    etiqueta: 'Color'
  },

  // Las opciones para este objeto se definen a continuación.
  opacidad de la ventana: {
    selector: '.vjs-ventana-opacidad > seleccionar',
    id: 'subtítulos-ventana-opacidad-%s',
    etiqueta: 'Transparencia',
    opciones: [
      OPACIDAD_TRANS,
      OPACIDAD_SEMI,
      OPACIDAD_OPACO
    ]
  }
};

selectConfigs.windowColor.options = selectConfigs.backgroundColor.options;

/**
 * Obtener el valor real de una opción.
 *
 * @param {cadena} valor
 * El valor a obtener
 *
 * @param {Función} [analizador]
 * Función opcional para ajustar el valor.
 *
 * @return {Mixto}
 * - Será `indefinido` si no existe ningún valor
 * - Será `indefinido` si el valor dado es "ninguno".
 * - Será el valor real en caso contrario.
 *
 * @privado
 * /
function parseOptionValue(valor, analizador) {
  si (analizador) {
    valor = analizador (valor);
  }

  si (valor && valor !== 'ninguno') {
    valor de retorno;
  }
}

/**
 * Obtiene el valor de lo seleccionado < opción> elemento dentro de un < seleccionar> elemento.
 *
 * @param {Elemento} el
 * el elemento a buscar
 *
 * @param {Función} [analizador]
 * Función opcional para ajustar el valor.
 *
 * @return {Mixto}
 * - Será `indefinido` si no existe ningún valor
 * - Será `indefinido` si el valor dado es "ninguno".
 * - Será el valor real en caso contrario.
 *
 * @privado
 * /
función getSelectedOptionValue(el, analizador) {
  const value = el.options[el.options.selectedIndex].value;

  return parseOptionValue(valor, analizador);
}

/**
 * Establece el seleccionado < opción> elemento dentro de un < seleccionar> elemento basado en un
 * valor dado.
 *
 * @param {Elemento} el
 * El elemento a buscar.
 *
 * @param {cadena} valor
 * la propiedad a mirar.
 *
 * @param {Función} [analizador]
 * Función opcional para ajustar el valor antes de comparar.
 *
 * @privado
 * /
función setSelectedOption(el, valor, analizador) {
  si (! valor) {
    devolver;
  }

  para (sea i = 0; i < el.opciones.longitud; i++) {
    if (parseOptionValue(el.options[i].value, parser) === valor) {
      el.selectedIndex = i;
      romper;
    }
  }
}

/**
 * Manipular la configuración de pistas de texto.
 *
 * @extiende ModalDialog
 * /
clase TextTrackSettings extiende ModalDialog {

  /**
   * 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) {
    opciones.temporal = falso;

    super(jugador, opciones);
    this.updateDisplay = this.updateDisplay.bind(this);

    // llena el modal y finge que lo hemos abierto
    esto.llenar();
    this.hasBeenOpened_ = this.hasBeenFilled_ = true;

    this.endDialog = createEl('p', {
      className: 'vjs-control-texto',
      textContent: this.localize('Fin de la ventana de diálogo.')
    });
    this.el().appendChild(this.endDialog);

    esto.setDefaults();

    // Toma `persistTextTrackSettings` de las opciones del reproductor si no se pasa en las opciones secundarias
    si (opciones.persistTextTrackSettings === indefinido) {
      this.options_.persistTextTrackSettings = this.options_.playerOptions.persistTextTrackSettings;
    }

    this.on(this.$('.vjs-done-button'), 'click', () => {
      this.saveSettings();
      esto.cerrar();
    });

    this.on(this.$('.vjs-default-button'), 'click', () => {
      esto.setDefaults();
      this.updateDisplay();
    });

    Obj.each(selectConfigs, config => {
      this.on(this.$(config.selector), 'cambiar', this.updateDisplay);
    });

    if (this.options_.persistTextTrackSettings) {
      esto.restoreSettings();
    }
  }

  disponer () {
    this.endDialog = null;

    super.dispose();
  }

  /**
   * Crear un < seleccionar> elemento con opciones configuradas.
   *
   * clave @param {cadena}
   * Clave de configuración para usar durante la creación.
   *
   * @return {cadena}
   * Una cadena HTML.
   *
   * @privado
   * /
  createElSelect_(clave, legendId = '', tipo = 'etiqueta') {
    const config = selectConfigs[clave];
    const id = config.id.replace('%s', this.id_);
    const selectLabelledbyIds = [legendId, id].join(' ').trim();

    devolver [
      `< ${tipo} id=&quot;${id}&quot; class=&quot;${tipo === 'etiqueta' ? 'vjs-label' : ''}&quot;> `,
      this.localize(config.label),
      `< /${tipo}> `,
      `< seleccione aria-labelledby=&quot;${selectLabelledbyIds}&quot;> `
    ].
      concat(config.options.map(o => {
        const optionId = id + '-' + o[1].replace(/\W+/g, '');

        devolver [
          `< opción id=&quot;${optionId}&quot; value=&quot;${o[0]}&quot; `,
          `aria-labelledby=&quot;${selectLabelledbyIds} ${optionId}&quot;> `,
          esto.localizar(o[1]),
          '< /opción> '
        ].unirse('');
      })).
      concat('< /seleccionar> ').unirse('');
  }

  /**
   * Crear elemento de color de primer plano para el componente
   *
   * @return {cadena}
   * Una cadena HTML.
   *
   * @privado
   * /
  crearElFgColor_() {
    const legendId = `captions-text-legend-${this.id_}`;

    devolver [
      '< fieldset class=&quot;vjs-fg-color vjs-track-setting&quot;> ',
      `< id de leyenda="${legendId}"> `,
      this.localize('Texto'),
      '</legend>',
      this.createElSelect_('color', legendId),
      '< span class=&quot;opacidad-texto-vjs opacidad-vjs&quot;> ',
      this.createElSelect_('textOpacity', legendId),
      '</span>',
      '</fieldset>'
    ].unirse('');
  }

  /**
   * Crear elemento de color de fondo para el componente
   *
   * @return {cadena}
   * Una cadena HTML.
   *
   * @privado
   * /
  crearElBgColor_() {
    const legendId = `captions-background-${this.id_}`;

    devolver [
      '< fieldset class=&quot;vjs-bg-color vjs-track-setting&quot;> ',
      `< id de leyenda="${legendId}"> `,
      this.localize('Fondo'),
      '</legend>',
      this.createElSelect_('backgroundColor', legendId),
      '< abarcan clase = &quot;vjs-bg-opacidad vjs-opacidad&quot;> ',
      this.createElSelect_('backgroundOpacity', legendId),
      '</span>',
      '</fieldset>'
    ].unirse('');
  }

  /**
   * Crear elemento de color de ventana para el componente
   *
   * @return {cadena}
   * Una cadena HTML.
   *
   * @privado
   * /
  crearElGanadorColor_() {
    const legendId = `captions-window-${this.id_}`;

    devolver [
      '< fieldset class=&quot;vjs-window-color vjs-track-setting&quot;> ',
      `< id de leyenda="${legendId}"> `,
      this.localize('Ventana'),
      '</legend>',
      this.createElSelect_('windowColor', legendId),
      '< span class=&quot;opacidad-ventana-vjs opacidad-vjs&quot;> ',
      this.createElSelect_('windowOpacity', legendId),
      '</span>',
      '</fieldset>'
    ].unirse('');
  }

  /**
   * Crear elementos de color para el componente.
   *
   * @return {Elemento}
   * El elemento que fue creado
   *
   * @privado
   * /
  crearElColors_() {
    return createEl('div', {
      className: 'vjs-track-settings-colores',
      HTML interno: [
        esto.createElFgColor_(),
        esto.createElBgColor_(),
        esto.createElWinColor_()
      ].unirse('')
    });
  }

  /**
   * Crear elementos de fuente para el componente
   *
   * @return {Elemento}
   * El elemento que se creó.
   *
   * @privado
   * /
  crearElFont_() {
    return createEl('div', {
      className: 'vjs-track-settings-fuente',
      HTML interno: [
        '< fieldset class=&quot;vjs-font-percent vjs-track-setting&quot;> ',
        this.createElSelect_('fontPercent', '', 'leyenda'),
        '</fieldset>',
        '< fieldset class=&quot;vjs-edge-style vjs-track-setting&quot;> ',
        this.createElSelect_('edgeStyle', '', 'leyenda'),
        '</fieldset>',
        '< fieldset class=&quot;vjs-font-family vjs-track-setting&quot;> ',
        this.createElSelect_('fontFamily', '', 'leyenda'),
        '</fieldset>'
      ].unirse('')
    });
  }

  /**
   * Crear controles para el componente
   *
   * @return {Elemento}
   * El elemento que se creó.
   *
   * @privado
   * /
  crearElControls_() {
    const defaultsDescription = this.localize('restaurar todas las configuraciones a los valores predeterminados');

    return createEl('div', {
      className: 'vjs-track-settings-controls',
      HTML interno: [
        `< tipo de botón = &quot;botón&quot; clase = &quot;vjs-default-button&quot; título = &quot;${defaultsDescription}&quot;> `,
        this.localize('Restablecer'),
        `< span class=&quot;vjs-control-texto&quot;> ${Descripción predeterminada}< /durar> `,
        '< /botón> ',
        `< tipo de botón = &quot;botón&quot; clase = &quot;vjs-hecho-botón&quot;> ${this.localize('Terminado')}< /botón> `
      ].unirse('')
    });
  }

  contenido() {
    devolver [
      this.createElColors_(),
      esto.createElFont_(),
      esto.createElControls_()
    ];
  }

  etiqueta() {
    return this.localize('Diálogo de configuración de subtítulos');
  }

  descripción() {
    return this.localize('Comienzo de la ventana de diálogo. Escape cancelará y cerrará la ventana.');
  }

  construirClaseCSS() {
    return super.buildCSSClass() + 'vjs-text-track-settings';
  }

  /**
   * Obtiene un objeto de configuración de pista de texto (o nulo).
   *
   * @return {Objeto}
   * Un objeto con valores de configuración analizados desde DOM o localStorage.
   * /
  obtenerValores() {
    return Obj.reduce(selectConfigs, (accum, config, key) => {
      valor const = getSelectedOptionValue(this.$(config.selector), config.parser);

      si (valor! == indefinido) {
        accum[clave] = valor;
      }

      volver acumular;
    }, {});
  }

  /**
   * Establece la configuración de la pista de texto de un objeto de valores.
   *
   * @param {Objeto} valores
   * Un objeto con valores de configuración analizados desde DOM o localStorage.
   * /
  establecerValores(valores) {
    Obj.each(selectConfigs, (config, key) => {
      setSelectedOption(this.$(config.selector), valores[clave], config.parser);
    });
  }

  /**
   * Establece todo `< seleccionar> ` elementos a sus valores predeterminados.
   * /
  Configurar valores predeterminados() {
    Obj.each(selectConfigs, (config) => {
      índice const = config.hasOwnProperty('predeterminado') ? config.predeterminado: 0;

      this.$(config.selector).selectedIndex = índice;
    });
  }

  /**
   * Restaurar la configuración de la pista de texto desde localStorage
   * /
  restaurar configuracion() {
    dejar valores;

    intentar {
      valores = JSON.parse(window.localStorage.getItem(LOCAL_STORAGE_KEY));
    } catch (err) {
      log.warn(err);
    }

    si (valores) {
      this.setValues(valores);
    }
  }

  /**
   * Guarde la configuración de la pista de texto en localStorage
   * /
  guardar ajustes() {
    if (!this.options_.persistTextTrackSettings) {
      devolver;
    }

    valores constantes = this.getValues();

    intentar {
      if (Objeto.claves(valores).longitud) {
        window.localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(valores));
      } else {
        ventana.localStorage.removeItem(LOCAL_STORAGE_KEY);
      }
    } catch (err) {
      log.warn(err);
    }
  }

  /**
   * Actualizar la visualización de la configuración de la pista de texto
   * /
  actualizarPantalla() {
    const ttDisplay = this.player_.getChild('textTrackDisplay');

    si (ttDisplay) {
      ttDisplay.updateDisplay();
    }
  }

  /**
   * desenfocar condicionalmente el elemento y volver a enfocar el botón de subtítulos
   *
   * @privado
   * /
  condicionalBlur_() {
    this.previouslyActiveEl_ = null;

    const cb = this.player_.controlBar;
    const subsCapsBtn = cb && cb.subsCapsButton;
    constante ccBtn = cb && cb.captionsButton;

    if (subsCapsBtn) {
      subsCapsBtn.focus();
    } si no (ccBtn) {
      ccBtn.foco();
    }
  }

}

Component.registerComponent('TextTrackSettings', TextTrackSettings);

exportar TextTrackSettings por defecto;