// F11. Бильярдная физика (§32 в ch4) — упругий удар + ЗСИ.
(function(){
'use strict';
const B = () => window.PHYS9_FLAG_BASE;
const C = () => window.PHYS9_COLORS || {};

function init(secId){
  if (!B()) return false;
  const body = ''
    + '<div style="margin-bottom:8px;font-size:.85rem;color:var(--muted)">Тяни мышью от белого шара — увидь прицельный вектор. Отпусти — удар. Длина перетягивания = сила удара.</div>'
    + '<canvas id="F11-cv" class="flag-canvas" width="700" height="380" style="height:380px;cursor:grab"></canvas>'
    + '<div class="flag-controls">'
      + '<button class="flag-btn primary" id="F11-reset">Расставить шары</button>'
      + '<button class="flag-btn" id="F11-clear">Очистить трассы</button>'
    + '</div>'
    + '<div class="flag-stats">'
      + '<div class="flag-stat"><span class="lbl">Σ импульса (до)</span><span class="val" id="F11-p0">0</span></div>'
      + '<div class="flag-stat"><span class="lbl">Σ импульса (сейчас)</span><span class="val" id="F11-pn">0</span></div>'
      + '<div class="flag-stat"><span class="lbl">Σ кин. энергии</span><span class="val" id="F11-E">0 Дж</span></div>'
      + '<div class="flag-stat"><span class="lbl">Кол-во шаров</span><span class="val" id="F11-n">4</span></div>'
    + '</div>'
    + '<div class="flag-feedback" id="F11-fb"></div>';

  const card = B().makeCard(secId,
    'F11. Бильярдная физика',
    'Упругий удар сохраняет и импульс, и кинетическую энергию. Σ p = const. Σ Ek = const (без трения).',
    body);
  if (!card) return false;

  const cv = document.getElementById('F11-cv');
  const ctx = cv.getContext('2d');
  const W = cv.width, H = cv.height;
  const R = 16;

  let balls = [];
  let aiming = false;
  let aimPos = { x: 0, y: 0 };
  let p0 = 0;  /* нач. импульс */
  let trails = [];

  function reset(){
    balls = [
      { x: W * 0.25, y: H * 0.5, vx: 0, vy: 0, color: '#fff', m: 1, label: 'биток' },
      { x: W * 0.65, y: H * 0.5,        vx: 0, vy: 0, color: '#fbbf24', m: 1, label: '1' },
      { x: W * 0.72, y: H * 0.5 - 20,   vx: 0, vy: 0, color: '#dc2626', m: 1, label: '2' },
      { x: W * 0.72, y: H * 0.5 + 20,   vx: 0, vy: 0, color: '#16a34a', m: 1, label: '3' }
    ];
    trails = [];
    p0 = 0;
    update();
    draw();
  }

  function update(){
    let px = 0, py = 0, E = 0;
    balls.forEach(b => {
      px += b.m * b.vx;
      py += b.m * b.vy;
      const v2 = b.vx*b.vx + b.vy*b.vy;
      E += b.m * v2 / 2;
    });
    document.getElementById('F11-p0').textContent = p0.toFixed(1) + ' (кг·px/с)';
    document.getElementById('F11-pn').textContent = Math.hypot(px, py).toFixed(1);
    document.getElementById('F11-E').textContent = (E*0.001).toFixed(2);
    document.getElementById('F11-n').textContent = balls.length;
  }

  function getPos(e){
    const rect = cv.getBoundingClientRect();
    const sx = cv.width / rect.width, sy = cv.height / rect.height;
    const x = ((e.touches ? e.touches[0].clientX : e.clientX) - rect.left) * sx;
    const y = ((e.touches ? e.touches[0].clientY : e.clientY) - rect.top) * sy;
    return { x, y };
  }

  function tick(dt){
    /* Шаги по dt — много мелких чтобы стабильно */
    const N = 4;
    const ddt = dt / N;
    for (let s = 0; s < N; s++){
      /* движение + трение */
      balls.forEach(b => {
        b.x += b.vx * ddt;
        b.y += b.vy * ddt;
        b.vx *= (1 - 0.05*ddt);
        b.vy *= (1 - 0.05*ddt);
        /* стенки */
        if (b.x < R){ b.x = R; b.vx = -b.vx*0.9; }
        if (b.x > W-R){ b.x = W-R; b.vx = -b.vx*0.9; }
        if (b.y < R){ b.y = R; b.vy = -b.vy*0.9; }
        if (b.y > H-R){ b.y = H-R; b.vy = -b.vy*0.9; }
        if (Math.hypot(b.vx, b.vy) < 1) { b.vx = b.vy = 0; }
      });
      /* столкновения */
      for (let i = 0; i < balls.length; i++){
        for (let j = i+1; j < balls.length; j++){
          const a = balls[i], b = balls[j];
          const dx = b.x - a.x, dy = b.y - a.y;
          const d2 = dx*dx + dy*dy;
          const minD = R*2;
          if (d2 < minD*minD && d2 > 1){
            const d = Math.sqrt(d2);
            const nx = dx/d, ny = dy/d;
            /* раздвинуть */
            const overlap = minD - d;
            a.x -= nx*overlap/2; a.y -= ny*overlap/2;
            b.x += nx*overlap/2; b.y += ny*overlap/2;
            /* упругий удар одинаковых масс */
            const va = a.vx*nx + a.vy*ny;
            const vb = b.vx*nx + b.vy*ny;
            if (vb - va > 0) continue;
            /* обмен компонентами вдоль нормали */
            a.vx += (vb - va)*nx; a.vy += (vb - va)*ny;
            b.vx += (va - vb)*nx; b.vy += (va - vb)*ny;
          }
        }
      }
    }
    /* trails */
    balls.forEach(b => {
      if (Math.hypot(b.vx, b.vy) > 5){
        trails.push({ x: b.x, y: b.y, c: b.color });
        if (trails.length > 800) trails.shift();
      }
    });
    update();
    draw();
  }

  function draw(){
    const col = C();
    /* зелёное поле */
    ctx.fillStyle = '#16a34a';
    ctx.fillRect(0, 0, W, H);
    /* ободок */
    ctx.strokeStyle = '#78350f';
    ctx.lineWidth = 8;
    ctx.strokeRect(4, 4, W-8, H-8);
    /* lunki по углам */
    ctx.fillStyle = '#0f172a';
    for (let cx of [12, W-12]) for (let cy of [12, H-12]) {
      ctx.beginPath(); ctx.arc(cx, cy, 10, 0, Math.PI*2); ctx.fill();
    }
    /* trails */
    trails.forEach(t => {
      ctx.fillStyle = t.c + '40';
      ctx.fillRect(t.x - 1, t.y - 1, 2, 2);
    });
    /* шары */
    balls.forEach(b => {
      ctx.fillStyle = b.color;
      ctx.beginPath(); ctx.arc(b.x, b.y, R, 0, Math.PI*2); ctx.fill();
      ctx.strokeStyle = '#0f172a';
      ctx.lineWidth = 1.5;
      ctx.stroke();
      if (b.label){
        ctx.fillStyle = b.color === '#fff' ? '#0f172a' : '#fff';
        ctx.font = 'bold 10px Inter,sans-serif';
        ctx.textAlign = 'center';
        ctx.fillText(b.label, b.x, b.y + 3);
        ctx.textAlign = 'left';
      }
    });
    /* aim */
    if (aiming){
      const biток = balls[0];
      ctx.strokeStyle = '#fff';
      ctx.lineWidth = 3;
      ctx.setLineDash([8, 4]);
      ctx.beginPath();
      ctx.moveTo(biток.x, biток.y);
      ctx.lineTo(biток.x*2 - aimPos.x, biток.y*2 - aimPos.y);
      ctx.stroke();
      ctx.setLineDash([]);
      const force = Math.hypot(biток.x - aimPos.x, biток.y - aimPos.y);
      ctx.fillStyle = '#fff';
      ctx.font = 'bold 13px Inter,sans-serif';
      ctx.fillText('сила: '+force.toFixed(0), 12, 22);
    }
  }

  cv.addEventListener('mousedown', e => {
    const p = getPos(e);
    const bit = balls[0];
    if (Math.hypot(p.x - bit.x, p.y - bit.y) < 40 && Math.hypot(bit.vx, bit.vy) < 1){
      aiming = true;
      aimPos = p;
    }
  });
  cv.addEventListener('mousemove', e => {
    if (aiming) { aimPos = getPos(e); draw(); }
  });
  cv.addEventListener('mouseup', e => {
    if (!aiming) return;
    aiming = false;
    const p = getPos(e);
    const bit = balls[0];
    bit.vx = (bit.x - p.x) * 2.5;
    bit.vy = (bit.y - p.y) * 2.5;
    p0 = Math.hypot(bit.m * bit.vx, bit.m * bit.vy);
    update();
  });

  document.getElementById('F11-reset').addEventListener('click', reset);
  document.getElementById('F11-clear').addEventListener('click', () => { trails = []; draw(); });

  reset();
  B().startLoop('F11', cv, tick);
  return true;
}

if (window.PHYS9_FLAG_BASE) window.PHYS9_FLAG_BASE.register('F11', { init: init, cleanup: function(){} });
else document.addEventListener('DOMContentLoaded', ()=>{
  if (window.PHYS9_FLAG_BASE) window.PHYS9_FLAG_BASE.register('F11', { init: init, cleanup: function(){} });
});

})();
