/**
 * @file resize-manager.js
 */
import window from 'global/window' ;
import { debounce } from './utils/fn.js' ;
import * as Events from './utils/events.js' ;
import mergeOptions from './utils/merge-options.js' ;
import Component from './component.js' ;

/**
 * Un gestionnaire de redimensionnement. Il est chargé de déclencher `playerresize` sur le joueur dans les bonnes conditions.
 *
 * Il créera une iframe et utilisera un gestionnaire de redimensionnement débloqué ou utilisera le nouveau {@link https://wicg.github.io/ResizeObserver/|ResizeObserver}.
 *
 * Si le ResizeObserver est disponible nativement, il sera utilisé. Un polyfill peut être passé en option.
 * Si l'événement `playerresize` n'est pas nécessaire, le composant ResizeManager peut être supprimé du lecteur, comme le montre l'exemple ci-dessous.
 * @exemple <caption>Comment désactiver le gestionnaire de redimensionnement</caption>
 * const player = videojs('#vid', {
 *   resizeManager : false
 * }) ;
 *
 * @see {@link https://wicg.github.io/ResizeObserver/|ResizeObserver specification}
 *
 * @extends Component
 */
class ResizeManager extends Component {

  /**
   * Créer le ResizeManager.
   *
   * @param {Objet} joueur
   *        Le `Player` auquel cette classe doit être attachée.
   *
   * @param {Objet} [options]
   *        Le magasin clé/valeur des options de ResizeManager.
   *
   * @param {Object} [options.ResizeObserver]
   *        Un polyfill pour ResizeObserver peut être passé ici.
   *        Si cette valeur est nulle, le ResizeObserver natif sera ignoré et le fallback de l'iframe sera utilisé.
   */
  constructor(player, options) {
    let RESIZE_OBSERVER_AVAILABLE = options.ResizeObserver || window.ResizeObserver ;

    // si `null` a été passé, nous voulons désactiver le ResizeObserver
    if (options.ResizeObserver === null) {
      RESIZE_OBSERVER_AVAILABLE = false ;
    }

    // Ne créer un élément que si ResizeObserver n'est pas disponible
    const options_ = mergeOptions({
      createEl : !RESIZE_OBSERVER_AVAILABLE,
      reportTouchActivity : false
    }, options) ;

    super(player, options_) ;

    this.ResizeObserver = options.ResizeObserver || window.ResizeObserver ;
    this.loadListener_ = null ;
    this.resizeObserver_ = null ;
    this.debouncedHandler_ = debounce(() => {
      this.resizeHandler() ;
    }, 100, false, this) ;

    if (RESIZE_OBSERVER_AVAILABLE) {
      this.resizeObserver_ = new this.ResizeObserver(this.debouncedHandler_) ;
      this.resizeObserver_.observe(player.el()) ;

    } else {
      this.loadListener_ = () => {
        if (!this.el_ || !this.el_.contentWindow) {
          retour ;
        }

        const debouncedHandler_ = this.debouncedHandler_ ;
        let unloadListener_ = this.unloadListener_ = function() {
          Events.off(this, 'resize', debouncedHandler_) ;
          Events.off(this, 'unload', unloadListener_) ;

          unloadListener_ = null ;
        };

        // safari et edge peuvent décharger l'iframe avant que resizemanager dispose
        // nous devons nous débarrasser correctement des gestionnaires d'événements avant que cela ne se produise
        Events.on(this.el_.contentWindow, 'unload', unloadListener_) ;
        Events.on(this.el_.contentWindow, 'resize', debouncedHandler_) ;
      };

      this.one('load', this.loadListener_) ;
    }
  }

  createEl() {
    return super.createEl('iframe', {
      className : 'vjs-resize-manager',
      tabIndex : -1,
      title : this.localize('Pas de contenu')
    }, {
      aria-hidden" : "true" (vrai)
    }) ;
  }

  /**
   * Appelé lorsqu'un redimensionnement est déclenché sur l'iframe ou lorsqu'un redimensionnement est observé via le ResizeObserver
   *
   * @fires Player#playerresize
   */
  resizeHandler() {
    /**
     * Appelé lorsque la taille du lecteur a changé
     *
     * @event Player#playerresize
     * @type {EventTarget~Event}
     */
    // s'assurer que le joueur est toujours présent pour déclencher l'action
    // évite de provoquer une erreur après l'élimination
    if (!this.player_ || !this.player_.trigger) {
      retour ;
    }

    this.player_.trigger('playerresize') ;
  }

  dispose() {
    if (this.debouncedHandler_) {
      this.debouncedHandler_.cancel() ;
    }

    if (this.resizeObserver_) {
      if (this.player_.el()) {
        this.resizeObserver_.unobserve(this.player_.el()) ;
      }
      this.resizeObserver_.disconnect() ;
    }

    if (this.loadListener_) {
      this.off('load', this.loadListener_) ;
    }

    if (this.el_ && this.el_.contentWindow && this.unloadListener_) {
      this.unloadListener_.call(this.el_.contentWindow) ;
    }

    this.ResizeObserver = null ;
    this.resizeObserver = null ;
    this.debouncedHandler_ = null ;
    this.loadListener_ = null ;
    super.dispose() ;
  }

}

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