// ct_graph.js
// Γραφική παράσταση C–t (ΘΕΩΡΗΤΙΚΟ ΜΟΝΤΕΛΟ)

(function () {

  const canvas = document.getElementById("ctCanvas");
  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 series = {
    A: { color: "#d32f2f", data: [] },
    B: { color: "#1976d2", data: [] },
    G: { color: "#388e3c", data: [] }
  };

  /* ===== οπτική μετατόπιση καμπυλών ===== */
  const VISUAL_OFFSETS = {
    A: -1.5,
    B: +1.5,
    G:  0
  };

  function addPoint(t, CA, CB, CG) {
    if (t > 0 && series.A.data.length === 0) {
      series.A.data.push({ t: 0, c: CA });
      series.B.data.push({ t: 0, c: CB });
      series.G.data.push({ t: 0, c: CG });
    }
    series.A.data.push({ t, c: CA });
    series.B.data.push({ t, c: CB });
    series.G.data.push({ t, c: CG });
  }

  function clear() {
    series.A.data = [];
    series.B.data = [];
    series.G.data = [];
  }

  /* ================= AXIS HELPERS ================= */
  function getTMax() {
    let tMax = 10;
    Object.values(series).forEach(s => {
      if (s.data.length) {
        tMax = Math.max(tMax, s.data[s.data.length - 1].t);
      }
    });
    return tMax;
  }

  function getCMaxRaw() {
    let m = 0;
    Object.values(series).forEach(s => {
      s.data.forEach(p => { if (p.c > m) m = p.c; });
    });
    return m;
  }

  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   };
    if (tMax <= 500)  return { major: 50, minor: 10  };
    return              { major: 100,minor: 50  };
  }

  /* ===== ΣΧΟΛΙΚΗ ΚΛΙΜΑΚΑ ΣΥΓΚΕΝΤΡΩΣΗΣ (ΜΟΝΟ MAJOR) ===== */
  function concScale(cMaxRaw) {

    const SCALES = [
      { max: 0.010, step: 0.001, decimals: 3 },
      { max: 0.020, step: 0.002, decimals: 3 },
      { max: 0.050, step: 0.005, decimals: 3 },
      { max: 0.100, step: 0.010, decimals: 2 },
      { max: 0.200, step: 0.020, decimals: 2 },
      { max: 0.500, step: 0.050, decimals: 2 },
      { max: 1.000, step: 0.100, decimals: 1 },
      { max: 2.000, step: 0.200, decimals: 1 },
      { max: 5.000, step: 0.500, decimals: 1 }
    ];

    for (const s of SCALES) {
      if (cMaxRaw <= s.max) {
        return {
          max: s.max,
          step: s.step,
          decimals: s.decimals
        };
      }
    }

    return { max: 10, step: 1, decimals: 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;
    const right  = w - 20;
    const top    = 20;
    const bottom = h - 75;

    const plotW = right - left;

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

    const tMax = getTMax();
    const tS   = timeScale(tMax);
    const cS   = concScale(getCMaxRaw());

    /* ===== 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("c (mol·L⁻¹)", 0, 0);
    ctx.restore();

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

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

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

    /* ===== CONCENTRATION GRID (ΜΟΝΟ MAJOR) ===== */
    for (let c = 0; c <= cS.max + 1e-9; c += cS.step) {
      const y = mapY(c, 0, cS.max, top, bottom);

      ctx.strokeStyle = "#ccc";
      ctx.beginPath();
      ctx.moveTo(left, y);
      ctx.lineTo(right, y);
      ctx.stroke();

      ctx.fillStyle = "#000";
      ctx.fillText(c.toFixed(cS.decimals), left - 55, y + 4);
    }

    /* ===== CURVES ===== */
    Object.entries(series).forEach(([key, s]) => {
      if (!s.data.length) return;

      const offsetY = VISUAL_OFFSETS[key] || 0;

      ctx.strokeStyle = s.color;
      ctx.lineWidth = 2;
      ctx.beginPath();

      s.data.forEach((p, i) => {
        const x = left + (p.t / tMax) * plotW;
        const yBase = mapY(p.c, 0, cS.max, top, bottom);
        const y = yBase + offsetY;

        if (i === 0) ctx.moveTo(x, y);
        else ctx.lineTo(x, y);
      });

      ctx.stroke();
      ctx.lineWidth = 1;
    });
  }

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

  /* ================= API ================= */
  window.CTGraph = {
    addPoint,
    clear,
    fitCanvas
  };

})();
