import { BRAND, ADS, getFormat } from './config.js';
import { renderSide } from './side.js';

const W = 320, H = 512, B = BRAND.blue, N = BRAND.ink;
const clamp = x => Math.max(0, Math.min(1, x));
const ease = x => 1 - Math.pow(1 - clamp(x), 4);
const smooth = x => { x = clamp(x); return x * x * (3 - 2 * x); };
const loadImage = src => new Promise((resolve, reject) => { const im = new Image(); im.onload = () => resolve(im); im.onerror = () => reject(new Error(`Missing asset: ${src}`)); im.src = src; });

export class Motion {
  constructor(canvas) { this.canvas = canvas; this.ctx = canvas.getContext('2d', { alpha: false }); this.bounds = []; }
  async init() {
    const [logo, lighting, lift] = await Promise.all([
      loadImage('/assets/logo-blue.png'), loadImage('/assets/generated/lighting.jpg'), loadImage('/assets/generated/lift.jpg'),
      document.fonts.load('800 40px Barlow', 'ABC ŠČĆŽĐ ščćžđ'), document.fonts.load('700 24px Manrope', 'ABC ŠČĆŽĐ ščćžđ'), document.fonts.load('500 20px Manrope', 'ABC ŠČĆŽĐ ščćžđ'),
    ]);
    this.logo = logo; this.lighting = lighting; this.lift = lift;
    return this;
  }
  rect(x, y, w, h, color) { this.ctx.fillStyle = color; this.ctx.fillRect(x, y, w, h); }
  line(points, color = B, width = 1.4, progress = 1, offset = 0) {
    const c = this.ctx; c.save(); c.strokeStyle = color; c.lineWidth = width; c.lineCap = 'round'; c.lineJoin = 'round';
    if (progress < 1) { c.setLineDash([Math.max(.01, progress * 1600), 1600]); c.lineDashOffset = offset; }
    c.beginPath(); points.forEach(([x, y], i) => i ? c.lineTo(x, y) : c.moveTo(x, y)); c.stroke(); c.restore();
  }
  text(str, x, y, size, { color = N, weight = 800, font = 'Barlow', align = 'left', max = 280, track = 0 } = {}) {
    const c = this.ctx; c.save(); c.fillStyle = color; c.font = `${weight} ${size}px ${font}`; c.textBaseline = 'alphabetic'; c.textAlign = align; c.letterSpacing = `${track}px`;
    const measured = c.measureText(str); const width = measured.width;
    if (width > max) { size *= max / width; c.font = `${weight} ${size}px ${font}`; }
    const m = c.measureText(str); const left = align === 'center' ? x - m.width / 2 : align === 'right' ? x - m.width : x;
    if(c.globalAlpha > .9) this.bounds.push({ str, left, right: left + m.width, top: y - m.actualBoundingBoxAscent, bottom: y + m.actualBoundingBoxDescent, size });
    c.fillText(str, x, y); c.restore();
  }
  reveal(str, x, y, size, t, start, opts = {}) {
    const p = ease((t - start) / .65); if (!p) return;
    const c = this.ctx; c.save(); c.beginPath(); c.rect(x - 2, y - size * 1.2, 294, size * 1.5); c.clip();
    c.globalAlpha *= p; c.translate(0, (1 - p) * (size + 10)); this.text(str, x, y, size, opts); c.restore();
  }
  logoMark(x, y, size) { const c=this.ctx;c.save();c.globalCompositeOperation='multiply';c.drawImage(this.logo, x, y, size, size);c.restore(); }
  brand(y = 26, alpha = 1) {
    const c = this.ctx; c.save(); c.globalAlpha *= alpha; this.logoMark(18, y - 14, 43);
    this.text('ELEKTRING', 67, y + 16, 26, { color: B, font: 'Manrope', weight: 700, track: -.8 }); c.restore();
  }
  base(t, warm = false) {
    const c = this.ctx; this.rect(0, 0, W, H, '#fff');
    const g = c.createRadialGradient(320, 330, 0, 320, 330, 310); g.addColorStop(0, warm ? '#fff9ee' : '#eef4ff'); g.addColorStop(1, '#fff');
    c.fillStyle = g; c.fillRect(0, 0, W, H);
    // Quiet architectural registration lines; the key messages stay in the safe area.
    this.line([[300, 76], [300, 459]], warm ? '#ece7dc' : '#e1e9f9', .75);
    const y = 90 + ((t * 21) % 340); this.rect(298.5, y, 3, 26, warm ? '#ceb884' : '#aac4ff');
  }
  layer(t, start, end, draw, { exit = .35 } = {}) {
    if (t < start || t >= end) return;
    const c = this.ctx; c.save();
    c.globalAlpha *= smooth((t - start) / .24) * smooth((end - t) / exit);
    draw(t - start); c.restore();
  }
  architecture(t, y = 320, scale = 1, alpha = 1) {
    const c = this.ctx; c.save(); c.globalAlpha *= alpha; c.translate(160, y); c.scale(scale, scale);
    const P = (x, y, z) => [(x - y) * .83, (x + y) * .36 - z];
    const paths = [
      [[-90,-65,0],[90,-65,0],[90,65,0],[-90,65,0],[-90,-65,0]],
      [[-90,-65,90],[90,-65,90],[90,65,90],[-90,65,90],[-90,-65,90]],
      [[-90,-65,0],[-90,-65,90]],[[90,-65,0],[90,-65,90]],[[90,65,0],[90,65,90]],[[-90,65,0],[-90,65,90]],
      [[-90,-65,90],[0,-65,140],[90,-65,90]], [[-90,65,90],[0,65,140],[90,65,90]], [[0,-65,140],[0,65,140]],
      [[-30,65,0],[-30,65,60],[6,65,60],[6,65,0]],
      [[35,65,43],[70,65,43],[70,65,71],[35,65,71],[35,65,43]],
      [[90,5,43],[90,-38,43],[90,-38,72],[90,5,72],[90,5,43]],
    ];
    paths.forEach((p, i) => this.line(p.map(a=>P(...a)), i < 2 ? '#99b4e8' : '#8da5c9', 1.2, ease((t - i * .025) / 1.8)));
    const circuits = [
      [[-130,75,0],[-90,75,0],[-90,65,0],[-90,65,76],[40,65,76],[40,65,43]],
      [[90,-110,0],[90,-65,0],[90,-65,82],[90,-10,82],[90,-10,44]],
      [[-90,65,76],[-90,0,76],[-90,0,90],[0,0,140]],
    ];
    circuits.forEach((p, i) => {
      const points = p.map(a=>P(...a)); this.line(points, B, 2.8, ease((t - .35 - i * .12) / 2));
      const q = (t * .22 + i * .32) % 1, lengths = points.slice(1).map((v,j)=>Math.hypot(v[0]-points[j][0],v[1]-points[j][1]));
      let d = lengths.reduce((a,b)=>a+b,0) * q;
      for(let j=0;j<lengths.length;j++){ if(d<=lengths[j]){const v=d/lengths[j]; c.fillStyle='#fff';c.strokeStyle=B;c.lineWidth=2;c.beginPath();c.arc(points[j][0]+v*(points[j+1][0]-points[j][0]),points[j][1]+v*(points[j+1][1]-points[j][1]),3.5,0,Math.PI*2);c.fill();c.stroke();break;} d-=lengths[j]; }
    }); c.restore();
  }
  photo(image, x, y, w, h, zoom = 1, position = .5) {
    const c=this.ctx; c.save(); c.beginPath();c.rect(x,y,w,h);c.clip();
    const s=Math.max(w/image.width,h/image.height)*zoom, dw=image.width*s, dh=image.height*s;
    c.drawImage(image,x+(w-dw)/2,y+(h-dh)*position,dw,dh); c.restore();
  }
  contact(t, ad) {
    this.layer(t, 10.5, 15, u => {
      this.rect(0,0,320,512,'#fff');
      this.brand(52);
      this.reveal(ADS[ad].cta,20,119,24,u,.08,{color:N});
      this.reveal(BRAND.website,20,166,31,u,.12,{color:B});
      this.line([[20,190],[300,190]],'#d6e1f6',1);
      BRAND.phones.forEach((phone,i)=>this.text(phone,20,224+i*29,23,{font:'Manrope',weight:700,track:-.5}));
      this.text(BRAND.email,20,327,19,{font:'Manrope',weight:700});
      this.text(BRAND.address,20,359,18,{font:'Manrope',weight:500});
      this.rect(20,403,34,3,B);
      this.text(BRAND.tagline,20,442,19,{font:'Manrope',weight:700,color:B,max:282,track:-.4});
      this.rect(0,494,320,18,B);
    },{exit:.38});
  }
  electro(t) {
    this.base(t);
    this.layer(t,0,2.45,u=>{
      this.architecture(u,451,1.23,.2);
      const p=ease(u/1.1); this.line([[20,279],[88,279],[112,255],[208,255],[232,247],[300,247]],B,2.5,p);
      const c=this.ctx;c.save();c.globalAlpha*=ease((u-.3)/.7);this.logoMark(102,81,116);c.restore();
      this.reveal('ELEKTRING',53,230,39,u,.5,{color:B,font:'Manrope',weight:700,track:-1.4,max:260});
      this.reveal('ENERGIJA KOJA',20,325,39,u,.72);
      this.reveal('POVEZUJE.',20,371,49,u,.86,{color:B});
    });
    this.layer(t,2.2,5.55,u=>{
      this.brand(); this.reveal('ELEKTRO',20,144,66,u,.05,{color:B});
      this.reveal('INSTALACIJE',20,204,58,u,.18);
      this.architecture(u+.3,392,.94);
      this.reveal('Pouzdano. Od temelja.',20,470,19,u,.48,{font:'Manrope',weight:700});
    });
    this.layer(t,5.3,8.45,u=>{
      this.brand(); this.architecture(u+2,445,.82,.26);
      [['STAMBENI',143],['POSLOVNI',211],['INDUSTRIJSKI',279]].forEach(([s,y],i)=>{
        this.reveal(s,20,y,49,u,.13+i*.25,{color:i===1?B:N});
        const p=ease((u-.15-i*.25)/.7);this.rect(20,y+15,278*p,1,'#cddcf5');
      }); this.reveal('OBJEKTI',20,332,26,u,1.05,{color:B,font:'Manrope',weight:700});
    });
    this.layer(t,8.2,10.75,u=>{
      this.brand();
      this.reveal('SIGURNO.',20,190,65,u,.06,{color:B});
      this.reveal('PRECIZNO.',20,256,61,u,.24);
      this.reveal('PROFESIONALNO.',20,319,46,u,.42);
      this.line([[20,365],[100,365],[125,340],[280,340]],B,3,ease(u/1.5));
    }); this.contact(t,'electro');
  }
  lightingAd(t) {
    this.base(t,true);
    this.layer(t,0,2.95,u=>{
      this.photo(this.lighting,0,0,320,512,1.08-.035*ease(u/3),.25);
      const c=this.ctx,g=c.createLinearGradient(0,290,0,500);g.addColorStop(0,'#ffffff00');g.addColorStop(.52,'#fffffff4');g.addColorStop(1,'#fff');c.fillStyle=g;c.fillRect(0,290,320,222);
      this.brand();this.reveal('NEKA BUDE',20,407,40,u,.45);
      this.reveal('SVJETLO.',20,462,61,u,.62,{color:B});
      const p=ease(u/1.5);c.globalAlpha*=1-p;this.rect(0,75,320,230,'#fff');
    });
    this.layer(t,2.7,6.65,u=>{
      this.photo(this.lighting,0,0,320,294,1.11-u*.007,.08);
      const c=this.ctx,g=c.createLinearGradient(0,214,0,301);g.addColorStop(0,'#ffffff00');g.addColorStop(1,'#fff');c.fillStyle=g;c.fillRect(0,214,320,90);
      this.rect(0,301,320,211,'#fff');this.brand();
      this.reveal('RASVJETA',20,342,63,u,.08,{color:B});
      this.reveal('KOJA MIJENJA',20,400,48,u,.24);
      this.reveal('PROSTOR.',20,463,64,u,.4);
    });
    this.layer(t,6.4,10.75,u=>{
      this.photo(this.lighting,0,275,320,237,1.4,.13);
      const c=this.ctx,g=c.createLinearGradient(0,260,0,330);g.addColorStop(0,'#fff');g.addColorStop(1,'#ffffff00');c.fillStyle=g;c.fillRect(0,260,320,80);
      this.brand();this.reveal('UNUTRAŠNJA',20,137,47,u,.1);
      this.reveal('VANJSKA',20,195,57,u,.4,{color:B});
      this.reveal('DEKORATIVNA',20,251,46,u,.7);
    }); this.contact(t,'lighting');
  }
  lifts(t) {
    this.base(t);
    this.layer(t,0,3.05,u=>{
      const c=this.ctx,p=ease(u/1.3);c.save();c.beginPath();c.rect(0,512*(1-p),320,512*p);c.clip();
      this.photo(this.lift,64,188+(1-p)*70,246,302,1,0.5);c.restore();
      this.brand();this.reveal('PODIGNITE',20,127,51,u,.35,{color:B});
      this.reveal('MOGUĆNOSTI.',20,179,47,u,.5);
      this.line([[30,426],[30,237],[20,247],[30,237],[40,247]],B,2,ease((u-.6)/1));
    });
    this.layer(t,2.8,6.25,u=>{
      const c=this.ctx;c.save();c.globalAlpha*=.24;this.photo(this.lift,100,110,230,360,1.12,.5);c.restore();
      this.brand();this.reveal('PRODAJA',20,211,79,u,.02,{color:B});
      this.reveal('&',22,274,59,u,.16);
      this.reveal('NAJAM',20,360,98,u,.28);
      this.reveal('OPREMA ZA RAD NA VISINI',20,444,25,u,.53,{color:B});
    });
    this.layer(t,6,10.75,u=>{
      this.brand();
      this.reveal('DIZALICE',20,123,54,u,.04,{color:B});
      this.reveal('I ŠKARASTE',20,174,49,u,.18);
      this.reveal('PLATFORME',20,225,49,u,.32);
      this.photo(this.lift,83,241-8*ease(u/4),200,261,1,.5);
      this.line([[37,459],[37,308],[26,319],[37,308],[48,319]],B,2.5,ease((u-.4)/1.3));
    });this.contact(t,'lifts');
  }
  render(ad, seconds) {
    if(!ADS[ad]) throw new Error('Unknown ad');
    const format = getFormat(ad);
    if(this.canvas.width !== format.width * 2 || this.canvas.height !== format.height * 2) {
      this.canvas.width = format.width * 2;
      this.canvas.height = format.height * 2;
    }
    const t=Math.max(0,Math.min(15,seconds));const c=this.ctx;this.bounds=[];
    if(ad==='side') {
      c.setTransform(2,0,0,2,0,0);c.globalAlpha=1;
      this.bounds=renderSide(c,this.logo,t);
      return this.bounds;
    }
    c.setTransform(this.canvas.width/W,0,0,this.canvas.height/H,0,0);c.globalAlpha=1;
    if(ad==='electro')this.electro(t);else if(ad==='lighting')this.lightingAd(t);else this.lifts(t);
    // All films meet on the same clean white frame for a deliberate loop transition.
    const fade=t<.18?1-smooth(t/.18):t>14.65?smooth((t-14.65)/.35):0;
    if(fade){c.save();c.globalAlpha=fade;this.rect(0,0,320,512,'#fff');c.restore();}
    return this.bounds;
  }
}
