/**
 * @archivo fn.js
 * @módulo fn
 * /
importar {nuevoGUID} desde './guid.js';
importar ventana desde 'global/window';

exportar const UPDATE_REFRESH_INTERVAL = 30;

/ **
 * Enlace (también conocido como proxy o contexto). Un método simple para cambiar el contexto de
 * Una función.
 *
 * También almacena una identificación única en la función para que pueda eliminarse fácilmente de
 * eventos.
 *
 * @función
 * @param {Mixto} contexto
 * El objeto a vincular como alcance.
 *
 * @param {Función} fn
 * La función que se vinculará a un ámbito.
 *
 * @param {número} [uid]
 * Una identificación única opcional para la función que se establecerá
 *
 * @return {Función}
 * La nueva función que se enlazará en el contexto dado
 * /
export const bind = función (contexto, fn, uid) {
  // Asegúrate de que la función tenga un ID único
  si (!fn.guid) {
    fn.guid = nuevoGUID();
  }

  // Crea la nueva función que cambia el contexto
  const enlazado = fn.bind(contexto);

  // Permitir la capacidad de individualizar esta función
  // Necesario en caso de que varios objetos puedan compartir el mismo prototipo
  // SI ambos elementos agregan un detector de eventos con la misma función, entonces intenta eliminar solo uno
  // eliminará ambos porque ambos tienen el mismo GUID.
  // al usar esto, también debe usar el método de vinculación cuando elimine el oyente.
  // utilizado actualmente en las pistas de texto
  enlazado.guid = (uid) ? uid + '_' + fn.guid : fn.guid;

  retorno obligado;
};

/ **
 * Envuelve la función dada, `fn`, con una nueva función que solo invoca `fn`
 * como máximo una vez por cada milisegundo de `espera`.
 *
 * @función
 * @param {Función} fn
 * La función a ser acelerada.
 *
 * @param {número} espera
 * El número de milisegundos por los cuales acelerar.
 *
 * @return {Función}
 * /
exportar aceleración constante = función (fn, esperar) {
  let last = ventana.rendimiento.ahora();

  const limitado = function(...args) {
    const ahora = ventana.rendimiento.ahora();

    si (ahora - último > = esperar) {
      fn(... argumentos);
      último = ahora;
    }
  };

  retorno estrangulado;
};

/ **
 * Crea una función antirrebote que retrasa la invocación de `func` hasta después de `wait`
 * han transcurrido milisegundos desde la última vez que se realizó la función antirrebote
 * invocado.
 *
 * Inspirado en las implementaciones de lodash y guión bajo.
 *
 * @función
 * @param {Función} función
 * La función para envolver con comportamiento antirrebote.
 *
 * @param {número} espera
 * El número de milisegundos a esperar después de la última invocación.
 *
 * @param {booleano} [inmediato]
 * Invocar o no la función inmediatamente después de la creación.
 *
 * @param {Objeto} [contexto=ventana]
 * El "contexto" en el que la función rebotada debe rebotar. Para
 * ejemplo, si esta función debe vincularse a un reproductor Video.js,
 * el jugador se puede pasar aquí. Alternativamente, el valor predeterminado es el
 * objeto `ventana` global.
 *
 * @return {Función}
 * Una función de rebote.
 * /
export const debounce = función (función, espera, inmediato, contexto = ventana) {
  dejar tiempo de espera;

  constante cancelar = () => {
    context.clearTimeout(tiempo de espera);
    tiempo de espera = nulo;
  };

  /* eslint-disable consistente-esto */
  const rebotado = función () {
    const self = esto;
    const argumentos = argumentos;

    let later = function() {
      tiempo de espera = nulo;
      más tarde = nulo;
      si (! inmediato) {
        func.apply(self, argumentos);
      }
    };

    si (! tiempo de espera && inmediato) {
      func.apply(self, argumentos);
    }

    context.clearTimeout(tiempo de espera);
    timeout = context.setTimeout(más tarde, esperar);
  };
  /* eslint-habilitar consistente-esto */

  cancelado.cancel = cancelar;

  devolución rebotada;
};