'use strict';
(function(global) {

  /* ── namespace (cooperative init) ── */
  global.LabFX = global.LabFX || {};

  /* ─────────────────────────────────────────────
     GLOW — Canvas 2D bloom helper
  ───────────────────────────────────────────── */
  global.LabFX.glow = {
    /**
     * Wraps drawFn with shadowBlur to create a soft glow.
     * For layers > 1 repeats drawFn with increasing intensity.
     */
    drawGlow: function(ctx, drawFn, opts) {
      opts = opts || {};
      var color     = opts.color     || '#fff';
      var intensity = opts.intensity != null ? opts.intensity : 12;
      var layers    = opts.layers    || 1;

      ctx.save();
      ctx.shadowColor = color;
      for (var i = 0; i < layers; i++) {
        ctx.shadowBlur = intensity * (i + 1);
        drawFn(ctx);
      }
      ctx.restore();
    },

    /**
     * Returns a 0..1 value that pulses over time.
     * @param {number} t      - current timestamp (ms), e.g. performance.now()
     * @param {number} period - full period in ms (default 1000)
     */
    pulse: function(t, period) {
      period = period || 1000;
      return (Math.sin((t / period) * Math.PI * 2) + 1) / 2;
    }
  };

  /* ─────────────────────────────────────────────
     HAPTIC — mobile vibration
  ───────────────────────────────────────────── */
  /**
   * @param {number|Array<number>} pattern - ms duration or [on,off,on,…]
   */
  global.LabFX.haptic = function(pattern) {
    if (!navigator.vibrate) return;
    navigator.vibrate(pattern);
  };

  /* ─────────────────────────────────────────────
     SHAKE — animate translate on a DOM element
  ───────────────────────────────────────────── */
  /**
   * @param {Element} elementOrCanvas
   * @param {object}  opts
   * @param {number}  opts.intensity - max translate px (default 5)
   * @param {number}  opts.durMs     - duration ms (default 200)
   */
  global.LabFX.shake = function(elementOrCanvas, opts) {
    opts = opts || {};
    var intensity = opts.intensity != null ? opts.intensity : 5;
    var durMs     = opts.durMs     != null ? opts.durMs     : 200;

    var el        = elementOrCanvas;
    var start     = performance.now();
    var origTransform = el.style.transform || '';

    function step(now) {
      var elapsed  = now - start;
      var progress = Math.min(elapsed / durMs, 1);
      var decay    = 1 - progress;
      var mag      = intensity * decay;
      var dx       = (Math.random() * 2 - 1) * mag;
      var dy       = (Math.random() * 2 - 1) * mag;

      el.style.transform = origTransform + ' translate(' + dx.toFixed(1) + 'px,' + dy.toFixed(1) + 'px)';

      if (progress < 1) {
        requestAnimationFrame(step);
      } else {
        el.style.transform = origTransform;
      }
    }

    requestAnimationFrame(step);
  };

})(window);
