/**
 * @file text-track-menu-item.js
 */
import MenuItem from '../../menu/menu-item.js' ;
import Component from '../../component.js' ;
import window from 'global/window' ;
import document from 'global/document' ;

/**
 * Le type d'élément de menu spécifique pour la sélection d'une langue dans un type de piste de texte
 *
 * @extends MenuItem
 */
class TextTrackMenuItem extends MenuItem {

  /**
   * Crée une instance de cette classe.
   *
   * @param {Player} player
   *        Le `Player` auquel cette classe doit être attachée.
   *
   * @param {Objet} [options]
   *        La mémoire clé/valeur des options du lecteur.
   */
  constructor(player, options) {
    const track = options.track ;
    const tracks = player.textTracks() ;

    // Modifier les options pour l'init de la classe MenuItem parente.
    options.label = track.label || track.language || 'Unknown' ;
    options.selected = track.mode === 'showing' ;

    super(player, options) ;

    this.track = track ;
    // Déterminer le(s) type(s) de pistes pertinent(s) pour ce composant et le filtrer
    // des types vides.
    this.kinds = (options.kinds || [options.kind || this.track.kind]).filter(Boolean) ;

    const changeHandler = (...args) => {
      this.handleTracksChange.apply(this, args) ;
    };
    const selectedLanguageChangeHandler = (...args) => {
      this.handleSelectedLanguageChange.apply(this, args) ;
    };

    player.on(['loadstart', 'texttrackchange'], changeHandler) ;
    tracks.addEventListener('change', changeHandler) ;
    tracks.addEventListener('selectedlanguagechange', selectedLanguageChangeHandler) ;
    this.on('dispose', function() {
      player.off(['loadstart', 'texttrackchange'], changeHandler) ;
      tracks.removeEventListener('change', changeHandler) ;
      tracks.removeEventListener('selectedlanguagechange', selectedLanguageChangeHandler) ;
    }) ;

    // iOS7 n'envoie pas d'événements de changement aux TextTrackLists lorsqu'un événement de type
    // le mode de la piste associée change. Sans quelque chose comme
    // Object.observe() (qui n'existe pas non plus sur iOS7), ce n'est pas
    // possibilité de détecter les modifications de l'attribut mode et du polyfill
    // l'événement de changement. En guise de substitut, nous envoyons manuellement
    // des événements de changement chaque fois que les contrôles modifient le mode.
    if (tracks.onchange === undefined) {
      laisser l'événement ;

      this.on(['tap', 'click'], function() {
        if (typeof window.Event !== 'object') {
          // Android 2.3 génère une erreur de constructeur illégal pour window.Event
          essayez {
            event = new window.Event('change') ;
          } catch (err) {
            // continuer sans tenir compte de l'erreur
          }
        }

        if (!event) {
          event = document.createEvent('Event') ;
          event.initEvent('change', true, true) ;
        }

        tracks.dispatchEvent(event) ;
      }) ;
    }

    // définir l'état par défaut en fonction des pistes actuelles
    this.handleTracksChange() ;
  }

  /**
   * Cette fonction est appelée lorsqu'un `TextTrackMenuItem` est "cliqué". Voir
   * {@link ClickableComponent} pour des informations plus détaillées sur ce que peut être un clic.
   *
   * @param {EventTarget~Event} event
   *        L'événement `keydown`, `tap` ou `click` qui a provoqué l'activation de cette fonction est le suivant
   *        appelé.
   *
   * @listens tap
   * @listens click
   */
  handleClick(event) {
    const referenceTrack = this.track ;
    const tracks = this.player_.textTracks() ;

    super.handleClick(event) ;

    if (!tracks) {
      retour ;
    }

    for (let i = 0 ; i < tracks.length ; i++) {
      const track = tracks[i] ;

      // Si la piste de la liste des pistes de texte n'est pas du bon type,
      // passer à l'étape suivante. Nous ne voulons pas affecter les pistes d'un ou de plusieurs types incompatibles.
      if (this.kinds.indexOf(track.kind) === -1) {
        continuer ;
      }

      // Si cette piste de texte est la piste du composant et qu'elle n'est pas affichée,
      // l'afficher.
      if (track === referenceTrack) {
        if (track.mode !== 'showing') {
          track.mode = 'showing' ;
        }

      // Si cette piste de texte n'est pas la piste du composant et qu'elle n'est pas
      // désactivé, lui attribuer la valeur "désactivé".
      } else if (track.mode !== 'disabled') {
        track.mode = 'disabled' ;
      }
    }
  }

  /**
   * Gestion des modifications de la liste des pistes de texte
   *
   * @param {EventTarget~Event} event
   *        L'événement `change` qui a provoqué l'appel de cette fonction.
   *
   * @listens TextTrackList#change
   */
  handleTracksChange(event) {
    const shouldBeSelected = this.track.mode === 'showing' ;

    // Empêchez les appels redondants à selected(), car ils peuvent causer des problèmes d'accès à l'information
    // les lecteurs d'écran lisent inutilement le texte de contrôle annexé
    if (shouldBeSelected !== this.isSelected_) {
      this.selected(shouldBeSelected) ;
    }
  }

  handleSelectedLanguageChange(event) {
    if (this.track.mode === 'showing') {
      const selectedLanguage = this.player_.cache_.selectedLanguage ;

      // Ne pas remplacer le type de piste dans la même langue
      if (selectedLanguage && selectedLanguage.enabled &&
        selectedLanguage.language === this.track.language &&
        selectedLanguage.kind !== this.track.kind) {
        retour ;
      }

      this.player_.cache_.selectedLanguage = {
        activé : vrai,
        langue : this.track.language,
        kind : this.track.kind
      };
    }
  }

  dispose() {
    // supprimer la référence à l'objet piste lors de l'élimination
    this.track = null ;

    super.dispose() ;
  }

}

Component.registerComponent('TextTrackMenuItem', TextTrackMenuItem) ;
export default TextTrackMenuItem ;