/**
 * Un objet qui contient des crochets de cycle de vie en tant que clés qui pointent vers un tableau
 * des fonctions qui sont exécutées lorsqu'un cycle de vie est déclenché
 *
 * @private
 */
const hooks_ = {} ;

/**
 * Obtenir une liste de crochets pour un cycle de vie spécifique
 *
 * @param {string} type
 *         le style de vie pour obtenir des crochets
 *
 * @param {Fonction|Fonction[]} [fn]
 *         Ajoutez éventuellement un (ou plusieurs) crochet(s) au cycle de vie que vous obtenez.
 *
 * @return {Array}
 *         un tableau de crochets, ou un tableau vide s'il n'y en a pas.
 */
const hooks = function(type, fn) {
  hooks_[type] = hooks_[type] || [] ;
  if (fn) {
    hooks_[type] = hooks_[type].concat(fn) ;
  }
  return hooks_[type] ;
};

/**
 * Ajouter un crochet de fonction à un cycle de vie vidéojs spécifique.
 *
 * @param {string} type
 *        le cycle de vie auquel la fonction doit être rattachée.
 *
 * @param {Fonction|Fonction[]}
 *        La fonction ou le tableau de fonctions à joindre.
 */
const hook = function(type, fn) {
  hooks(type, fn) ;
};

/**
 * Supprime un crochet d'un cycle de vie vidéojs spécifique.
 *
 * @param {string} type
 *         le cycle de vie auquel la fonction est liée
 *
 * @param {Fonction} fn
 *         La fonction crochetée pour supprimer
 *
 * @return {boolean}
 *         La fonction qui a été supprimée ou undef
 */
const removeHook = function(type, fn) {
  const index = hooks(type).indexOf(fn) ;

  if (index <= -1) {
    retourner faux ;
  }

  hooks_[type] = hooks_[type].slice() ;
  hooks_[type].splice(index, 1) ;

  retourner vrai ;
};

/**
 * Ajoutez un crochet de fonction qui ne s'exécutera qu'une seule fois à un cycle de vie vidéojs spécifique.
 *
 * @param {string} type
 *        le cycle de vie auquel la fonction doit être rattachée.
 *
 * @param {Fonction|Fonction[]}
 *        La fonction ou le tableau de fonctions à joindre.
 */
const hookOnce = function(type, fn) {
  hooks(type, [].concat(fn).map(original => {
    const wrapper = (...args) => {
      removeHook(type, wrapper) ;
      return original(...args) ;
    };

    return wrapper ;
  })) ;
};

export {
  crochets_,
  crochets,
  crochet,
  hookOnce,
  Retirer le crochet
};