/**
 * @file time-tooltip.js
 */
import Component from '../../component' ;
import * as Dom from '../../utils/dom.js' ;
import formatTime from '../../utils/format-time.js' ;
import * as Fn from '../../utils/fn.js' ;

/**
 * Les infobulles temporelles affichent une durée au-dessus de la barre de progression.
 *
 * @extends Component
 */
class TimeTooltip extends Component {

  /**
   * Crée une instance de cette classe.
   *
   * @param {Player} player
   *        Le {@link 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.update = Fn.throttle(Fn.bind(this, this.update), Fn.UPDATE_REFRESH_INTERVAL) ;
  }

  /**
   * Créer l'élément DOM de l'info-bulle sur l'heure
   *
   * @return {Element}
   *         L'élément qui a été créé.
   */
  createEl() {
    return super.createEl('div', {
      className : 'vjs-time-tooltip'
    }, {
      aria-hidden" : "true" (vrai)
    }) ;
  }

  /**
   * Met à jour la position de l'info-bulle de l'heure par rapport à la `SeekBar`.
   *
   * @param {Object} seekBarRect
   *        Le `ClientRect` de l'élément {@link SeekBar}.
   *
   * @param {number} seekBarPoint
   *        Un nombre compris entre 0 et 1, représentant un point de référence horizontal
   *        à partir du bord gauche de la {@link SeekBar}
   */
  update(seekBarRect, seekBarPoint, content) {
    const tooltipRect = Dom.findPosition(this.el_) ;
    const playerRect = Dom.getBoundingClientRect(this.player_.el()) ;
    const seekBarPointPx = seekBarRect.width * seekBarPoint ;

    // ne rien faire si l'un ou l'autre rect n'est pas disponible
    // par exemple, si le joueur n'est pas dans le DOM pour le test
    if (!playerRect || !tooltipRect) {
      retour ;
    }

    // C'est l'espace à gauche du `seekBarPoint` disponible à l'intérieur des limites
    // du joueur. Nous calculons tout écart entre le bord gauche du joueur
    // et le bord gauche de la `SeekBar` et ajoutez le nombre de pixels dans le champ
    // Rechercher la barre avant d'atteindre le point de recherche (`seekBarPoint`)
    const spaceLeftOfPoint = (seekBarRect.left - playerRect.left) + seekBarPointPx ;

    // C'est l'espace à droite du `seekBarPoint` disponible à l'intérieur des limites
    // du joueur. Nous calculons le nombre de pixels à partir du `seekBarPoint`
    // au bord droit de la `SeekBar` et ajoutez-y l'écart entre la `SeekBar` et le bord droit de la `SeekBar`
    // bord droit de la `SeekBar` et du lecteur.
    const spaceRightOfPoint = (seekBarRect.width - seekBarPointPx) +
      (playerRect.right - seekBarRect.right) ;

    // Il s'agit du nombre de pixels dont l'infobulle devra être tirée
    // plus à droite pour le centrer sur le `seekBarPoint`.
    let pullTooltipBy = tooltipRect.width / 2 ;

    // Ajuster la distance `pullTooltipBy` vers la gauche ou la droite en fonction de
    // les résultats des calculs d'espace ci-dessus.
    if (spaceLeftOfPoint < pullTooltipBy) {
      pullTooltipBy += pullTooltipBy - spaceLeftOfPoint ;
    } else if (spaceRightOfPoint < pullTooltipBy) {
      pullTooltipBy = spaceRightOfPoint ;
    }

    // En raison de l'imprécision des calculs basés sur les décimales/ratios et de la variation des taux d'intérêt, le système d'échange de quotas d'émission a été modifié
    // comportements d'arrondi, il y a des cas où l'ajustement de l'espacement n'est pas correct
    // d'un ou deux pixels. Cela ajoute une assurance à ces calculs.
    if (pullTooltipBy < 0) {
      pullTooltipBy = 0 ;
    } else if (pullTooltipBy > tooltipRect.width) {
      pullTooltipBy = tooltipRect.width ;
    }

    // empêche les petites fluctuations de largeur dans les 0,4px de
    // modifier la valeur ci-dessous.
    // Cela permet d'éviter le jeu en direct
    // l'info-bulle sur le temps de progression n'est pas gérable
    pullTooltipBy = Math.round(pullTooltipBy) ;

    this.el_.style.right = `-${pullTooltipBy}px` ;
    this.write(content) ;
  }

  /**
   * Inscrire l'heure dans l'élément DOM de l'infobulle.
   *
   * @param {string} content
   *        L'heure formatée pour l'infobulle.
   */
  write(content) {
    Dom.textContent(this.el_, content) ;
  }

  /**
   * Met à jour la position de l'info-bulle de l'heure par rapport à la `SeekBar`.
   *
   * @param {Object} seekBarRect
   *        Le `ClientRect` de l'élément {@link SeekBar}.
   *
   * @param {number} seekBarPoint
   *        Un nombre compris entre 0 et 1, représentant un point de référence horizontal
   *        à partir du bord gauche de la {@link SeekBar}
   *
   * @param {number} time
   *        Heure de mise à jour de l'infobulle, non utilisée lors de la lecture en direct
   *
   * @param {Fonction} cb
   *        Une fonction qui sera appelée pendant l'image d'animation de la demande
   *        pour les infobulles qui ont besoin d'animations supplémentaires par rapport à l'animation par défaut
   */
  updateTime(seekBarRect, seekBarPoint, time, cb) {
    this.requestNamedAnimationFrame('TimeTooltip#updateTime', () => {
      laisser le contenu ;
      const duration = this.player_.duration() ;

      if (this.player_.liveTracker && this.player_.liveTracker.isLive()) {
        const liveWindow = this.player_.liveTracker.liveWindow() ;
        const secondsBehind = liveWindow - (seekBarPoint * liveWindow) ;

        content = (secondsBehind < 1 ? '' : '-') + formatTime(secondsBehind, liveWindow) ;
      } else {
        content = formatTime(time, duration) ;
      }

      this.update(seekBarRect, seekBarPoint, content) ;
      if (cb) {
        cb() ;
      }
    }) ;
  }
}

Component.registerComponent('TimeTooltip', TimeTooltip) ;
exporter l'info-bulle par défaut TimeTooltip ;