/**
 * @file volume-control.js
 */
import Component from '../component.js' ;
import {isPlain} from '../utils/obj' ;
import * as Events from '../utils/events.js' ;
import keycode from 'keycode' ;
import document from 'global/document' ;

// Enfants requis
import './volume-control/volume-control.js' ;
import './mute-toggle.js' ;

/**
 * Un composant contenant le MuteToggle et le VolumeControl de manière à ce que
 * ils peuvent travailler ensemble.
 *
 * @extends Component
 */
class VolumePanel extends Component {

  /**
   * 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 = {}) {
    if (typeof options.inline !== 'undefined') {
      options.inline = options.inline ;
    } else {
      options.inline = true ;
    }

    // transmettre l'option inline au VolumeControl en tant que vertical if
    // la commande de volume est activée.
    if (typeof options.volumeControl === 'undefined' || isPlain(options.volumeControl)) {
      options.volumeControl = options.volumeControl || {} ;
      options.volumeControl.vertical = !options.inline ;
    }

    super(player, options) ;

    // ce gestionnaire est utilisé par les méthodes de gestion de la souris ci-dessous
    this.handleKeyPressHandler_ = (e) => this.handleKeyPress(e) ;

    this.on(player, ['loadstart'], (e) => this.volumePanelState_(e)) ;
    this.on(this.muteToggle, 'keyup', (e) => this.handleKeyPress(e)) ;
    this.on(this.volumeControl, 'keyup', (e) => this.handleVolumeControlKeyUp(e)) ;
    this.on('keydown', (e) => this.handleKeyPress(e)) ;
    this.on('mouseover', (e) => this.handleMouseOver(e)) ;
    this.on('mouseout', (e) => this.handleMouseOut(e)) ;

    // lorsque le curseur est actif (la souris a été enfoncée et le curseur a été déplacé)
    // est en train de glisser) nous ne voulons pas cacher le VolumeBar
    this.on(this.volumeControl, ['slideractive'], this.sliderActive_) ;

    this.on(this.volumeControl, ['sliderinactive'], this.sliderInactive_) ;
  }

  /**
   * Ajouter la classe vjs-slider-active au VolumePanel
   *
   * @listens VolumeControl#slideractive
   * @private
   */
  sliderActive_() {
    this.addClass('vjs-slider-active') ;
  }

  /**
   * Supprime la classe vjs-slider-active du VolumePanel
   *
   * @listens VolumeControl#sliderinactive
   * @private
   */
  sliderInactive_() {
    this.removeClass('vjs-slider-active') ;
  }

  /**
   * Ajoute vjs-hidden ou vjs-mute-toggle-only au VolumePanel
   * en fonction de l'état de MuteToggle et de VolumeControl
   *
   * @listens Player#loadstart
   * @private
   */
  volumePanelState_() {
    // cacher le panneau de volume s'il n'y a pas de contrôle du volume ou de basculement vers la sourdine
    // sont affichés
    if (this.volumeControl.hasClass('vjs-hidden') && this.muteToggle.hasClass('vjs-hidden')) {
      this.addClass('vjs-hidden') ;
    }

    // si seul le bouton de mise en sourdine est visible, nous ne le voulons pas
    // le panneau de volume s'agrandit lorsqu'il est survolé ou actif
    if (this.volumeControl.hasClass('vjs-hidden') && !this.muteToggle.hasClass('vjs-hidden')) {
      this.addClass('vjs-mute-toggle-only') ;
    }
  }

  /**
   * Créer l'élément DOM du `Composant`
   *
   * @return {Element}
   *         L'élément qui a été créé.
   */
  createEl() {
    let orientationClass = 'vjs-volume-panel-horizontal' ;

    if (!this.options_.inline) {
      orientationClass = 'vjs-volume-panel-vertical' ;
    }

    return super.createEl('div', {
      className : `vjs-volume-panel vjs-control ${orientationClass}`
    }) ;
  }

  /**
   * Se débarrasser de `volume-panel` et de tous les composants enfants.
   */
  dispose() {
    this.handleMouseOut() ;
    super.dispose() ;
  }

  /**
   * Gère les événements `keyup` sur le `VolumeControl`, en recherchant ESC, qui ferme
   * le panneau de volume et met l'accent sur `MuteToggle`.
   *
   * @param {EventTarget~Event} event
   *        L'événement `keyup` qui a provoqué l'appel de cette fonction.
   *
   * @listens keyup
   */
  handleVolumeControlKeyUp(event) {
    if (keycode.isEventKey(event, 'Esc')) {
      this.muteToggle.focus() ;
    }
  }

  /**
   * Cette fonction est appelée lorsqu'un `VolumePanel` gagne un hover via un événement `mouseover`.
   * Active l'écoute de l'événement `mouseover`. Lorsqu'ils se produisent, il
   * appelle `this.handleMouseOver`.
   *
   * @param {EventTarget~Event} event
   *        L'événement `mouseover` qui a provoqué l'appel de cette fonction.
   *
   * @listens mouseover
   */
  handleMouseOver(event) {
    this.addClass('vjs-hover') ;
    Events.on(document, 'keyup', this.handleKeyPressHandler_) ;
  }

  /**
   * Cette fonction est appelée lorsqu'un `VolumePanel` gagne un hover via un événement `mouseout`.
   * Active l'écoute de l'événement `mouseout`. Lorsqu'ils se produisent, il
   * appelle `this.handleMouseOut`.
   *
   * @param {EventTarget~Event} event
   *        L'événement `mouseout` qui a provoqué l'appel de cette fonction.
   *
   * @listens mouseout
   */
  handleMouseOut(event) {
    this.removeClass('vjs-hover') ;
    Events.off(document, 'keyup', this.handleKeyPressHandler_) ;
  }

  /**
   * Gère l'événement `keyup` sur le document ou l'événement `keydown` sur le `VolumePanel`,
   * à la recherche de ESC, qui cache le `VolumeControl`.
   *
   * @param {EventTarget~Event} event
   *        La touche qui a déclenché cet événement.
   *
   * @listens keydown | keyup
   */
  handleKeyPress(event) {
    if (keycode.isEventKey(event, 'Esc')) {
      this.handleMouseOut() ;
    }
  }
}

/**
 * Options par défaut pour la commande `VolumeControl`
 *
 * @type {Objet}
 * @private
 */
VolumePanel.prototype.options_ = {
  enfants : [
    'muteToggle',
    volumeControl
  ]
};

Component.registerComponent('VolumePanel', VolumePanel) ;
exporter le VolumePanel par défaut ;