/* GeoSegment — landing page (mobile first) */
const { useState, useEffect, useRef, useCallback } = React;

// ── Icons ──────────────────────────────────────────────
const IconPdf = () => (
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round">
    <path d="M14 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8z" />
    <path d="M14 3v5h5" />
    <path d="M9 13h6M9 17h4" />
  </svg>
);
const IconMap = () => (
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round">
    <path d="M9 4 3 6v14l6-2 6 2 6-2V4l-6 2-6-2z" />
    <path d="M9 4v14M15 6v14" />
  </svg>
);
const IconArrow = () => (
  <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
    <path d="M3 8h10M9 4l4 4-4 4" />
  </svg>
);
const IconDownload = () => (
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round">
    <path d="M12 4v12M6 10l6 6 6-6M4 20h16" />
  </svg>
);

// ── Before/after comparison ────────────────────────────
function Compare({ interactive }) {
  const [cut, setCut] = useState(2);
  const ref = useRef(null);
  const dragging = useRef(false);
  const touchStart = useRef(null);
  // null = undecided, 'h' = horizontal (slider), 'v' = vertical (scroll)
  const lockedAxis = useRef(null);
  const LOCK_THRESHOLD = 8; // px before we commit to a direction

  // Intro animation: starts extreme right, sweeps to left, settles center
  useEffect(() => {
    let raf;
    const start = performance.now();
    const duration = 950; // ms total
    const animate = (now) => {
      const t = Math.min((now - start) / duration, 1);
      let value;
      if (t < 0.55) {
        // fast sweep: 2 → 95 (easeOutQuart — decelerates as it reaches right)
        const p = t / 0.55;
        const ease = 1 - Math.pow(1 - p, 4);
        value = 2 + (95 - 2) * ease;
      } else {
        // settle: 95 → 50 (easeInOutCubic — smooth snap to center)
        const p = (t - 0.55) / 0.45;
        const ease = p < 0.5 ? 4 * p * p * p : 1 - Math.pow(-2 * p + 2, 3) / 2;
        value = 95 + (50 - 95) * ease;
      }
      setCut(value);
      if (t < 1) raf = requestAnimationFrame(animate);
    };
    raf = requestAnimationFrame(animate);
    return () => cancelAnimationFrame(raf);
  }, []);

  const updateFromClientX = useCallback((x) => {
    const el = ref.current;
    if (!el) return;
    const rect = el.getBoundingClientRect();
    const pct = ((x - rect.left) / rect.width) * 100;
    setCut(Math.max(2, Math.min(98, pct)));
  }, []);

  useEffect(() => {
    if (!interactive) return;
    const onMove = (e) => {
      if (!dragging.current) return;
      if (e.touches) {
        const dx = Math.abs(e.touches[0].clientX - touchStart.current.x);
        const dy = Math.abs(e.touches[0].clientY - touchStart.current.y);
        // wait until movement passes threshold before locking direction
        if (lockedAxis.current === null) {
          if (dx < LOCK_THRESHOLD && dy < LOCK_THRESHOLD) return;
          lockedAxis.current = dx >= dy ? 'h' : 'v';
        }
        if (lockedAxis.current === 'v') { dragging.current = false; return; }
        e.preventDefault();
        updateFromClientX(e.touches[0].clientX);
      } else {
        updateFromClientX(e.clientX);
      }
    };
    const onUp = () => {
      dragging.current = false;
      touchStart.current = null;
      lockedAxis.current = null;
    };
    window.addEventListener('mousemove', onMove);
    window.addEventListener('mouseup', onUp);
    window.addEventListener('touchmove', onMove, { passive: false });
    window.addEventListener('touchend', onUp);
    return () => {
      window.removeEventListener('mousemove', onMove);
      window.removeEventListener('mouseup', onUp);
      window.removeEventListener('touchmove', onMove);
      window.removeEventListener('touchend', onUp);
    };
  }, [interactive, updateFromClientX]);

  const onHandleDown = (e) => {
    if (!interactive) return;
    e.stopPropagation();
    dragging.current = true;
    lockedAxis.current = null;
    if (e.touches) {
      touchStart.current = { x: e.touches[0].clientX, y: e.touches[0].clientY };
    } else {
      updateFromClientX(e.clientX);
    }
  };

  return (
    <div
      className={"compare" + (interactive ? "" : " static")}
      ref={ref}
      style={{ "--cut": cut + "%" }}
      role={interactive ? "slider" : undefined}
      aria-valuenow={Math.round(cut)}
      aria-label="Comparação imagem aérea vs segmentação"
    >
      {/* Base layer = segmentação (revealed on the right of the cut) */}
      <img src="assets/segmented-real.png" alt="Segmentação por aprendizado profundo" />
      {/* Overlay clipped to the LEFT of the cut = imagem aérea original */}
      <div className="compare-mask">
        <img src="assets/aerial-real.png" alt="Imagem aérea original" />
      </div>
      <span className="compare-label left">Imagem aérea</span>
      <span className="compare-label right">Segmentação</span>
      {interactive
        ? <div
            className="compare-handle"
            onMouseDown={onHandleDown}
            onTouchStart={onHandleDown}
            style={{ cursor: "ew-resize" }}
          >
            <div className="line" />
            <span className="compare-arrow left">‹</span>
            <span className="compare-arrow right">›</span>
          </div>
        : <div className="compare-handle"><div className="line" /></div>
      }
    </div>
  );
}

// ── CTA card ───────────────────────────────────────────
function Cta({ href, download, primary, icon, title, meta, pill }) {
  const external = !download && href && href.startsWith("http");
  return (
    <a
      className={"cta" + (primary ? " primary" : "")}
      href={href}
      download={download || undefined}
      target={external ? "_blank" : undefined}
      rel={external ? "noopener noreferrer" : undefined}
    >
      <span className="cta-icon">{icon}</span>
      <span className="cta-body">
        <span className="cta-title">
          {title}
          {pill && <span className="cta-pill">{pill}</span>}
        </span>
        <span className="cta-meta">{meta}</span>
      </span>
      <span className="cta-arrow"><IconArrow /></span>
    </a>
  );
}

// ── Tweaks state ───────────────────────────────────────
const PALETTES = {
  forest:  ["#0d4a1f", "#2d8a3e", "#3fa53b"],
  vibrant: ["#0d4a1f", "#3fa53b", "#7be08e"],
  earth:   ["#5a3a17", "#9c6a2a", "#c4933f"],
  ocean:   ["#0c3a5e", "#1f6fb2", "#3a96d4"],
};

const AUTHORS = [
  { name: "Deise Adriana Silva Araújo", email: "deeh_adriana@hotmail.com" },
  { name: "Gustavo Dias Vicentin", email: "gusvic2501@gmail.com" },
  { name: "Lucas Rebouças Silva", email: "lucasreboucas100@gmail.com" },
  { name: "Victor Caldeira Iak", email: "victorciak2013@gmail.com" },
  { name: "Vinicius Saidi Soares", email: "saidi-soares@hotmail.com" },
];

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "theme": "light",
  "palette": ["#0d4a1f", "#2d8a3e", "#3fa53b"],
  "interactiveCompare": true,
  "showAbout": true,
  "pixelMotif": 0.5,
  "softwareUrl": "https://geo-segmentation-frontend-production.up.railway.app/"
}/*EDITMODE-END*/;

function App() {
  const [t, setTweak] = window.useTweaks(TWEAK_DEFAULTS);

  // Apply theme + accent
  useEffect(() => {
    document.documentElement.dataset.theme = t.theme || "light";
    const p = Array.isArray(t.palette) ? t.palette : PALETTES.forest;
    document.documentElement.style.setProperty("--forest", p[0]);
    document.documentElement.style.setProperty("--pixel", p[1]);
    document.documentElement.style.setProperty("--pixel-bright", p[2]);
    document.documentElement.style.setProperty("--pixel-bg-opacity", String(t.pixelMotif ?? 0.5));
  }, [t.theme, t.palette, t.pixelMotif]);

  return (
    <>
      <div className="pixel-bg" aria-hidden="true" />
      <main className="page">
        <header className="topbar fade-up">
          <div className="brand">
            <div className="brand-mark" aria-hidden="true">
              <span /><span /><span /><span /><span /><span /><span /><span /><span />
            </div>
            <span>GeoSegment</span>
          </div>
          <span className="tag-tcc">INOVA FEI · 2026</span>
        </header>

        <section className="hero">
          <span className="hero-eyebrow fade-up d1">Mapeamento via Aprendizado Profundo</span>
          <h1 className="hero-title fade-up d2">
            Desvendando o mundo,<br />
            um <span className="pixel-word">pixel</span> por vez
          </h1>
          <p className="hero-sub fade-up d3">
            Identificamos automaticamente o que há em imagens aéreas: floresta,
            vegetação, solo exposto e área urbana, para apoiar a fiscalização ambiental.
          </p>

          <div className="fade-up d3">
            <Compare interactive={t.interactiveCompare} />
          </div>

          <div className="legend fade-up d4">
            <span className="legend-item"><span className="legend-swatch" style={{ background: "#1e7800" }} /> Floresta</span>
            <span className="legend-item"><span className="legend-swatch" style={{ background: "#78d278" }} /> Vegetação</span>
            <span className="legend-item"><span className="legend-swatch" style={{ background: "#963c1e" }} /> Solo exposto</span>
            <span className="legend-item"><span className="legend-swatch" style={{ background: "#ff0000" }} /> Urbano</span>
          </div>

          <p className="hero-sub fade-up d4" style={{ marginTop: 16 }}>
            Em termos simples: enviamos uma imagem aérea capturada por drone ou satélite e
            o sistema devolve um mapa colorido dizendo o que há em cada parte do terreno,
            sem nenhuma intervenção humana. Isso permite que órgãos ambientais monitorem
            grandes áreas de floresta em minutos, tarefa que antes exigia semanas de trabalho de campo.
          </p>
        </section>

        <section className="fade-up d4">
          <div className="section-head">
            <span className="num">01</span>
            <h2>Comece por aqui</h2>
          </div>

          <div className="actions">
            <Cta
              primary
              href={t.softwareUrl || "#"}
              icon={<IconMap />}
              title="Acessar o software"
              meta="Demo online · Railway"
              pill="Software"
            />
            <Cta
              href="assets/trabalho-2-paginas.pdf"
              download
              icon={<IconPdf />}
              title="Resumo expandido"
              meta="PDF · 2 páginas"
              pill="Leitura rápida"
            />
            <Cta
              href="assets/trabalho-12-paginas.pdf"
              download
              icon={<IconDownload />}
              title="Trabalho completo"
              meta="PDF · 12 páginas"
              pill="Aprofundamento"
            />
          </div>
        </section>

        {t.showAbout && (
          <section className="fade-up d5">
            <div className="section-head">
              <span className="num">02</span>
              <h2>Desempenho científico</h2>
            </div>
            <p className="section-lede">
              Resultados do modelo <em>GeoSegment-Geral</em> treinado com 322 imagens
              públicas do Google Earth.
            </p>
            <div className="metrics">
              <div className="metric">
                <div className="metric-value">81,56<span>%</span></div>
                <div className="metric-key">mIoU</div>
                <div className="metric-desc">Intersecção sobre União · métrica principal em segmentação semântica</div>
              </div>
              <div className="metric">
                <div className="metric-value">89,80<span>%</span></div>
                <div className="metric-key">OA</div>
                <div className="metric-desc">Acurácia global · fração de pixels classificados corretamente</div>
              </div>
              {/* <div className="metric">
                <div className="metric-value">83<span>%</span></div>
                <div className="metric-key">F1 Macro</div>
                <div className="metric-desc">Média harmônica entre precisão e revocação</div>
              </div> */}
            </div>
          </section>
        )}

        <section className="fade-up d5">
          <div className="section-head">
            <span className="num">03</span>
            <h2>Classes identificadas</h2>
          </div>
          <p className="section-lede">
            Cada pixel da imagem aérea é classificado em uma das 8 categorias
            de uso e cobertura do solo.
          </p>
          <div className="classes">
            {[
              { c: "#1e7800", n: "Vegetação Densa" },
              { c: "#78d278", n: "Vegetação Esparsa" },
              { c: "#1f6fb2", n: "Água" },
              { c: "#963c1e", n: "Solo Exposto" },
              { c: "#ff0000", n: "Urbano" },
              { c: "#ffd400", n: "Agricultura" },
              { c: "#8a8a8a", n: "Rocha" },
              { c: "#1a1a1a", n: "Sombra" },
            ].map((cls, i) => (
              <div className="class-row" key={i}>
                <span className="class-swatch" style={{ background: cls.c }} />
                <span className="class-name">{cls.n}</span>
              </div>
            ))}
          </div>
        </section>

        <section className="fade-up d5">
          <div className="section-head">
            <span className="num">04</span>
            <h2>Arquitetura técnica</h2>
          </div>
          <div className="arch-grid">
            <div className="arch-card">
              <div className="arch-tag">Modelo</div>
              <div className="arch-title">DeepLabV3+ · ResNet-101</div>
              <div className="arch-body">
                Codificador pré-treinado, função de perda composta
                (Focal + Dice + Entropia Cruzada).
              </div>
            </div>
            <div className="arch-card">
              <div className="arch-tag">Dados</div>
              <div className="arch-title">322 imagens públicas</div>
              <div className="arch-body">
                Capturas do Google Earth com resolução média de
                <strong> 50 cm/pixel</strong>.
              </div>
            </div>
            <div className="arch-card">
              <div className="arch-tag">Otimização</div>
              <div className="arch-title">Optuna · Santos Dumont</div>
              <div className="arch-body">
                Busca automática de hiperparâmetros no supercomputador
                nacional do LNCC.
              </div>
            </div>
          </div>
        </section>

        {t.showAbout && (
          <section className="about fade-up d5">
            <div className="section-head" style={{ marginTop: 0 }}>
              <span className="num">05</span>
              <h2>Sobre o trabalho</h2>
            </div>
            <dl className="about-rows">
              <dt>Tema</dt>
              <dd>Mapeamento de uso e cobertura do solo via aprendizado profundo em imagens aéreas</dd>
              <dt>Instituição</dt>
              <dd>Centro Universitário FEI</dd>
              <dt>Parceria</dt>
              <dd>ICMBio (MMA) e LNCC</dd>
              <dt>Programa</dt>
              <dd>Iniciação Científica INOVA FEI · 2026</dd>
            </dl>
          </section>
        )}

        <section className="authors fade-up d6">
          <div className="section-head">
            <span className="num">06</span>
            <h2>Autores</h2>
          </div>
          <p className="section-lede">
            Ciência da Computação, campus São Bernardo do Campo
          </p>
          <ul className="authors-list">
            {AUTHORS.map((author) => (
              <li className="author-row" key={author.email}>
                <span className="author-name">{author.name}</span>
                <a className="author-email" href={"mailto:" + author.email}>
                  {author.email}
                </a>
              </li>
            ))}
          </ul>
        </section>

        <section className="partners fade-up d6">
          <div className="partners-label">Realização e parceria</div>
          <div className="partners-grid">
            <div className="partner">
              <img src="assets/logo-fei.png" alt="Centro Universitário FEI" />
            </div>
            <div className="partner">
              <img src="assets/logo-icmbio.png" alt="ICMBio — MMA" />
            </div>
            <div className="partner">
              <img src="assets/logo-lncc.png" alt="LNCC" />
            </div>
          </div>
        </section>

        <footer className="foot fade-up d6">
          <span>© 2026 GeoSegment</span>
          <span>v1.0 · pixel-first</span>
        </footer>
      </main>

      {/* Tweaks panel — same React tree so state is shared */}
      <window.TweaksPanel title="Tweaks">
        <window.TweakSection label="Tema">
          <window.TweakRadio
            value={t.theme}
            onChange={(v) => setTweak("theme", v)}
            options={[
              { value: "light", label: "Claro" },
              { value: "dark", label: "Escuro" },
            ]}
          />
        </window.TweakSection>

        <window.TweakSection label="Paleta">
          <window.TweakColor
            value={t.palette}
            onChange={(v) => setTweak("palette", v)}
            options={[
              PALETTES.forest,
              PALETTES.vibrant,
              PALETTES.earth,
              PALETTES.ocean,
            ]}
          />
        </window.TweakSection>

        <window.TweakSection label="Slider arrastável">
          <window.TweakToggle
            value={t.interactiveCompare}
            onChange={(v) => setTweak("interactiveCompare", v)}
            label="Comparação"
          />
        </window.TweakSection>

        <window.TweakSection label="Seção sobre o trabalho">
          <window.TweakToggle
            value={t.showAbout}
            onChange={(v) => setTweak("showAbout", v)}
            label="Mostrar"
          />
        </window.TweakSection>

        <window.TweakSection label="Motivo pixel (fundo)">
          <window.TweakSlider
            value={t.pixelMotif}
            onChange={(v) => setTweak("pixelMotif", v)}
            min={0} max={1} step={0.1}
          />
        </window.TweakSection>

        <window.TweakSection label="URL do software">
          <window.TweakText
            value={t.softwareUrl}
            onChange={(v) => setTweak("softwareUrl", v)}
          />
        </window.TweakSection>
      </window.TweaksPanel>
    </>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
