/* Particle text effect for the hero — adapted to: transparent over video,
   Nunito font, brand palette (white + orange), scroll-aware (pauses when hidden). */

(function(){
  const { useRef, useEffect } = React;

  function rand(a,b){ return Math.random()*(b-a)+a; }

  class P {
    constructor(){
      this.pos={x:0,y:0}; this.vel={x:0,y:0}; this.acc={x:0,y:0}; this.target={x:0,y:0};
      this.closeEnough=100; this.maxSpeed=1; this.maxForce=0.1; this.size=2; this.killed=false;
      this.sc={r:0,g:0,b:0}; this.tc={r:255,g:255,b:255}; this.cw=0; this.cbr=0.01;
    }
    move(){
      let prox=1;
      const dx=this.pos.x-this.target.x, dy=this.pos.y-this.target.y;
      const d=Math.hypot(dx,dy);
      if(d<this.closeEnough) prox=d/this.closeEnough;
      let tx=this.target.x-this.pos.x, ty=this.target.y-this.pos.y;
      const m=Math.hypot(tx,ty);
      if(m>0){ tx=tx/m*this.maxSpeed*prox; ty=ty/m*this.maxSpeed*prox; }
      let sx=tx-this.vel.x, sy=ty-this.vel.y;
      const sm=Math.hypot(sx,sy);
      if(sm>0){ sx=sx/sm*this.maxForce; sy=sy/sm*this.maxForce; }
      this.acc.x+=sx; this.acc.y+=sy;
      this.vel.x+=this.acc.x; this.vel.y+=this.acc.y;
      this.pos.x+=this.vel.x; this.pos.y+=this.vel.y;
      this.acc.x=0; this.acc.y=0;
    }
    draw(ctx,sz){
      if(this.cw<1) this.cw=Math.min(this.cw+this.cbr,1);
      const r=Math.round(this.sc.r+(this.tc.r-this.sc.r)*this.cw);
      const g=Math.round(this.sc.g+(this.tc.g-this.sc.g)*this.cw);
      const b=Math.round(this.sc.b+(this.tc.b-this.sc.b)*this.cw);
      ctx.fillStyle=`rgb(${r},${g},${b})`;
      ctx.fillRect(this.pos.x,this.pos.y,sz,sz);
    }
    kill(w,h){
      if(this.killed) return;
      const rp=randPos(w/2,h/2,(w+h)/2);
      this.target.x=rp.x; this.target.y=rp.y;
      this.sc={ r:this.sc.r+(this.tc.r-this.sc.r)*this.cw, g:this.sc.g+(this.tc.g-this.sc.g)*this.cw, b:this.sc.b+(this.tc.b-this.sc.b)*this.cw };
      this.tc={r:0,g:0,b:0}; this.cw=0; this.killed=true;
    }
  }
  function randPos(x,y,mag){
    const rx=Math.random()*1000, ry=Math.random()*500;
    let dx=rx-x, dy=ry-y; const m=Math.hypot(dx,dy);
    if(m>0){ dx=dx/m*mag; dy=dy/m*mag; }
    return { x:x+dx, y:y+dy };
  }

  function ParticleHero({ words, palette, align }){
    const canvasRef=useRef(null), wrapRef=useRef(null), rafRef=useRef(0);
    const parts=useRef([]), frame=useRef(0), wi=useRef(0), dprRef=useRef(1), wordsRef=useRef(words);
    wordsRef.current = (words && words.length) ? words : ["BEAVRDAM"];
    const PIX=4;
    const pal = palette || [{r:226,g:232,b:240},{r:255,g:140,b:0}];

    useEffect(()=>{
      const canvas=canvasRef.current, wrap=wrapRef.current;
      if(!canvas||!wrap) return;
      const ctx=canvas.getContext("2d");

      function size(){
        const dpr=Math.min(window.devicePixelRatio||1,2); dprRef.current=dpr;
        const w=wrap.clientWidth, h=wrap.clientHeight;
        canvas.width=Math.max(2,Math.round(w*dpr));
        canvas.height=Math.max(2,Math.round(h*dpr));
        canvas.style.width=w+"px"; canvas.style.height=h+"px";
      }

      function nextWord(word){
        const W=canvas.width, H=canvas.height;
        const off=document.createElement("canvas"); off.width=W; off.height=H;
        const o=off.getContext("2d");
        let fs=Math.min(Math.floor(H*1.05), Math.round(122*dprRef.current));
        const family="900 "+fs+"px Nunito, sans-serif";
        o.font=family; o.textAlign=align||"left"; o.textBaseline="middle";
        const pad=Math.round(W*0.01);
        const maxW=W*0.92;
        while(o.measureText(word).width > maxW && fs>10){ fs-=2; o.font="900 "+fs+"px Nunito, sans-serif"; }
        o.fillStyle="#fff";
        const tx = (align==="center") ? W/2 : pad;
        o.fillText(word, tx, H/2 + fs*0.02);
        const px=o.getImageData(0,0,W,H).data;

        const color = pal[wi.current % pal.length];
        const arr=parts.current; let pi=0;
        const idxs=[];
        for(let i=0;i<px.length;i+=PIX*4) idxs.push(i);
        for(let i=idxs.length-1;i>0;i--){ const j=(Math.random()*(i+1))|0; [idxs[i],idxs[j]]=[idxs[j],idxs[i]]; }
        for(const ci of idxs){
          if(px[ci+3]>0){
            const x=(ci/4)%W, y=Math.floor(ci/4/W);
            let p;
            if(pi<arr.length){ p=arr[pi]; p.killed=false; pi++; }
            else {
              p=new P();
              const rp=randPos(W/2,H/2,(W+H)/2); p.pos.x=rp.x; p.pos.y=rp.y;
              p.maxSpeed=rand(4,10); p.maxForce=p.maxSpeed*0.05;
              p.size=Math.max(1,Math.round(dprRef.current*1.4)); p.cbr=rand(0.0025,0.03);
              arr.push(p);
            }
            p.sc={ r:p.sc.r+(p.tc.r-p.sc.r)*p.cw, g:p.sc.g+(p.tc.g-p.sc.g)*p.cw, b:p.sc.b+(p.tc.b-p.sc.b)*p.cw };
            p.tc=color; p.cw=0; p.target.x=x; p.target.y=y;
          }
        }
        for(let i=pi;i<arr.length;i++) arr[i].kill(W,H);
      }

      function animate(){
        const heroEl=document.getElementById("hero");
        const vis = !heroEl || parseFloat(heroEl.style.opacity||"1") > 0.02;
        if(vis){
          const W=canvas.width, H=canvas.height, arr=parts.current;
          ctx.globalCompositeOperation="destination-out";
          ctx.fillStyle="rgba(0,0,0,0.18)";
          ctx.fillRect(0,0,W,H);
          ctx.globalCompositeOperation="source-over";
          for(let i=arr.length-1;i>=0;i--){
            const p=arr[i]; p.move(); p.draw(ctx,p.size);
            if(p.killed && (p.pos.x<0||p.pos.x>W||p.pos.y<0||p.pos.y>H)) arr.splice(i,1);
          }
          frame.current++;
          if(frame.current % 230 === 0){
            wi.current=(wi.current+1)%wordsRef.current.length;
            nextWord(wordsRef.current[wi.current]);
          }
        }
        rafRef.current=requestAnimationFrame(animate);
      }

      let ro;
      const boot=()=>{ size(); wi.current=0; parts.current=[]; nextWord(wordsRef.current[0]); };
      boot();
      // refresh glyph metrics once the webfont actually loads (non-blocking)
      if(document.fonts && document.fonts.ready){
        document.fonts.ready.then(()=>{ try{ nextWord(wordsRef.current[wi.current]); }catch(e){} });
      }
      animate();

      let rt=0;
      ro=new ResizeObserver(()=>{ clearTimeout(rt); rt=setTimeout(()=>{ size(); nextWord(wordsRef.current[wi.current]); },150); });
      ro.observe(wrap);

      return ()=>{ cancelAnimationFrame(rafRef.current); if(ro) ro.disconnect(); };
    },[]);

    return (
      <div ref={wrapRef} className="hero-canvas-wrap">
        <canvas ref={canvasRef}></canvas>
      </div>
    );
  }

  window.ParticleHero = ParticleHero;
})();
