// vt_graph.js
// Γραφική παράσταση υ–t (ΘΕΩΡΗΤΙΚΟ ΜΟΝΤΕΛΟ)
// Καμπύλη υ–t με δυναμική κλίμακα (rolling autoscale)

(function () {

  const canvas = document.getElementById("vtCanvas");
  if (!canvas) return;
  const ctx = canvas.getContext("2d");

  /* ================= CANVAS ================= */
  function fitCanvas() {
    const r = canvas.getBoundingClientRect();
    const dpr = window.devicePixelRatio || 1;
    canvas.width  = Math.floor(r.width * dpr);
    canvas.height = Math.floor(r.height * dpr);
    ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
  }
  window.addEventListener("resize", fitCanvas);
  fitCanvas();

  /* ================= DATA ================= */
  const dataF = [];
  const dataR = [];
  let vInitial = null;

  const WINDOW_T = 4;   // sec – χρονικό παράθυρο autoscale

  function addPoint(t, vF, vR) {
    if (dataF.length === 0 && t > 0) {
      dataF.push({ t: 0, v: vF });
      dataR.push({ t: 0, v: vR });
    }
    dataF.push({ t, v: vF });
    dataR.push({ t, v: vR });
  }

  function clear() {
    dataF.length = 0;
    dataR.length = 0;
    vInitial = null;
  }

  /* ================= AXIS HELPERS ================= */

  function getTMax() {
    if (!dataF.length) return 10;
    return Math.max(10, dataF[dataF.length - 1].t);
  }

  function timeScale(tMax) {
    if (tMax <= 10)  return { major: 1, minor: 0.5 };
    if (tMax <= 20)  return { major: 2, minor: 1 };
    if (tMax <= 50)  return { major: 5, minor: 1 };
    if (tMax <= 100) return { major: 10, minor: 5 };
    return { major: 20, minor: 10 };
  }

  function rateScale(vMax) {
    if (vMax <= 0) return { max: 1e-2, step: 1e-3, dec: 3 };

    const S = [
      { max: 1e-2, step: 1e-3, dec: 3 },
      { max: 5e-2, step: 5e-3, dec: 3 },
      { max: 1e-1, step: 1e-2, dec: 2 },
      { max: 1,    step: 0.1,  dec: 1 },
      { max: 10,   step: 1,    dec: 0 },
      { max: 50,   step: 5,    dec: 0 },
      { max: 100,  step: 10,   dec: 0 }
    ];
    return S.find(s => vMax <= s.max) || { max: 200, step: 20, dec: 0 };
  }

  function mapY(v, min, max, top, bottom) {
    return bottom - (v - min) / (max - min) * (bottom - top);
  }

  /* ================= DRAW ================= */
  function draw() {
    const w = canvas.clientWidth;
    const h = canvas.clientHeight;
    if (w < 20 || h < 20) return;

    ctx.clearRect(0, 0, w, h);

    const left = 85, right = w - 20;
    const top = 20, bottom = h - 75;

    ctx.strokeStyle = "#000";
    ctx.lineWidth = 2;
    ctx.strokeRect(left, top, right - left, bottom - top);
    ctx.lineWidth = 1;

    const tMax = getTMax();
    const tS = timeScale(tMax);

    /* ===== DYNAMIC vMax (rolling window) ===== */
    let vMax = 0;
    const tNow = dataF.length ? dataF[dataF.length - 1].t : 0;

    dataF.forEach(p => {
      if (tNow - p.t <= WINDOW_T) vMax = Math.max(vMax, p.v);
    });
    dataR.forEach(p => {
      if (tNow - p.t <= WINDOW_T) vMax = Math.max(vMax, p.v);
    });

    if (vMax === 0 && vInitial !== null) {
      vMax = vInitial;
    }

    vMax *= 1.15;   // padding

    const vS = rateScale(vMax);

    /* ===== LABELS ===== */
    ctx.fillStyle = "#000";
    ctx.font = "bold 18px Arial";
    ctx.fillText("t (s)", (left + right) / 2 - 18, h - 35);

    ctx.save();
    ctx.translate(18, (top + bottom) / 2);
    ctx.rotate(-Math.PI / 2);
    ctx.fillText("υ (mol·L⁻¹·s⁻¹)", 0, 0);
    ctx.restore();

    /* ===== GRID ===== */
    ctx.font = "14px Arial";

    for (let t = 0; t <= tMax; t += tS.minor) {
      const x = left + (t / tMax) * (right - left);
      ctx.strokeStyle = "#eee";
      ctx.beginPath();
      ctx.moveTo(x, top);
      ctx.lineTo(x, bottom);
      ctx.stroke();
    }

    for (let t = 0; t <= tMax; t += tS.major) {
      const x = left + (t / tMax) * (right - left);
      ctx.strokeStyle = "#ccc";
      ctx.beginPath();
      ctx.moveTo(x, top);
      ctx.lineTo(x, bottom);
      ctx.stroke();
      ctx.fillStyle = "#000";
      ctx.fillText(t, x - 6, bottom + 22);
    }

    for (let v = 0; v <= vS.max; v += vS.step) {
      const y = mapY(v, 0, vS.max, top, bottom);
      ctx.strokeStyle = "#ccc";
      ctx.beginPath();
      ctx.moveTo(left, y);
      ctx.lineTo(right, y);
      ctx.stroke();
      ctx.fillText(v.toFixed(vS.dec), left - 45, y + 4);
    }

    /* ===== CURVES ===== */
    if (dataF.length >= 2) {
      ctx.strokeStyle = "#a89a01ff";
      ctx.lineWidth = 4;
      ctx.beginPath();
      dataF.forEach((p, i) => {
        const x = left + (p.t / tMax) * (right - left);
        const y = mapY(p.v, 0, vS.max, top, bottom);
        if (i === 0) ctx.moveTo(x, y);
        else ctx.lineTo(x, y);
      });
      ctx.stroke();
    }

    if (dataR.length >= 2) {
      ctx.strokeStyle = "#741181ff";
      ctx.lineWidth = 4;
      ctx.beginPath();
      dataR.forEach((p, i) => {
        const x = left + (p.t / tMax) * (right - left);
        const y = mapY(p.v, 0, vS.max, top, bottom);
        if (i === 0) ctx.moveTo(x, y);
        else ctx.lineTo(x, y);
      });
      ctx.stroke();
    }

    ctx.font = "bold 22px Arial";
    ctx.fillStyle = "#a89a01ff";
    ctx.fillText("υ→", right - 60, top + 18);
    ctx.fillStyle = "#741181ff";
    ctx.fillText("υ←", right - 60, top + 36);
  }

  function raf() {
    draw();
    requestAnimationFrame(raf);
  }
  requestAnimationFrame(raf);

  /* ================= API ================= */
  window.VTGraph = {
    addPoint,
    clear,
    fitCanvas,
    setInitialRate(v) {
      if (isFinite(v)) vInitial = v;
    }
  };

})();
