/**
 * @file load-progress-bar.js
 */
import Component from '../../component.js' ;
import * as Dom from '../../utils/dom.js' ;
import clamp from '../../utils/clamp' ;
import document from 'global/document' ;

// obtenir le pourcentage de largeur d'un temps par rapport au total fin
const percentify = (time, end) => clamp((time / end) * 100, 0, 100).toFixed(2) + '%' ;

/**
 * Affiche l'état d'avancement du chargement
 *
 * @extends Component
 */
class LoadProgressBar 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) {
    super(player, options) ;
    this.partEls_ = [] ;
    this.on(player, 'progress', (e) => this.update(e)) ;
  }

  /**
   * Créer l'élément DOM du `Composant`
   *
   * @return {Element}
   *         L'élément qui a été créé.
   */
  createEl() {
    const el = super.createEl('div', {className : 'vjs-load-progress'}) ;
    const wrapper = Dom.createEl('span', {className : 'vjs-control-text'}) ;
    const loadedText = Dom.createEl('span', {textContent : this.localize('Loaded')}) ;
    const separator = document.createTextNode(' : ') ;

    this.percentageEl_ = Dom.createEl('span', {
      className : 'vjs-control-text-loaded-percentage',
      textContent : '0%'
    }) ;

    el.appendChild(wrapper) ;
    wrapper.appendChild(loadedText) ;
    wrapper.appendChild(separator) ;
    wrapper.appendChild(this.percentageEl_) ;

    return el ;
  }

  dispose() {
    this.partEls_ = null ;
    this.percentageEl_ = null ;

    super.dispose() ;
  }

  /**
   * Mise à jour de la barre de progression
   *
   * @param {EventTarget~Event} [event]
   *        L'événement `progress` qui a provoqué l'exécution de cette fonction.
   *
   * @listens Player#progress
   */
  update(event) {
    this.requestNamedAnimationFrame('LoadProgressBar#update', () => {
      const liveTracker = this.player_.liveTracker ;
      const buffered = this.player_.buffered() ;
      const duration = (liveTracker && liveTracker.isLive()) ? liveTracker.seekableEnd() : this.player_.duration() ;
      const bufferedEnd = this.player_.bufferedEnd() ;
      const children = this.partEls_ ;
      const percent = percentify(bufferedEnd, duration) ;

      if (this.percent_ !== percent) {
        // mettre à jour la largeur de la barre de progression
        this.el_.style.width = percent ;
        // mettre à jour le texte du contrôle
        Dom.textContent(this.percentageEl_, percent) ;
        this.percent_ = percent ;
      }

      // ajouter des éléments enfants pour représenter les différentes plages de temps mises en mémoire tampon
      for (let i = 0 ; i < buffered.length ; i++) {
        const start = buffered.start(i) ;
        const end = buffered.end(i) ;
        let part = children[i] ;

        if (!part) {
          part = this.el_.appendChild(Dom.createEl()) ;
          enfants[i] = partie ;
        }

        // ne mettre à jour qu'en cas de changement
        if (part.dataset.start === start && part.dataset.end === end) {
          continuer ;
        }

        part.dataset.start = start ;
        part.dataset.end = end ;

        // fixer le pourcentage en fonction de la largeur de la barre de progression (bufferedEnd)
        part.style.left = percentify(start, bufferedEnd) ;
        part.style.width = percentify(end - start, bufferedEnd) ;
      }

      // supprimer les éléments inutilisés de la plage tamponnée
      for (let i = children.length ; i > buffered.length ; i--) {
        this.el_.removeChild(children[i - 1]) ;
      }
      children.length = buffered.length ;
    }) ;
  }
}

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