/* WeatherMate — radar screen (RainViewer, no API key) */

const RAINVIEWER_API = "https://api.rainviewer.com/public/weather-maps.json";

/* Tile URL helpers */
function radarTile(host, path, z, x, y) {
  return `${host}${path}/256/${z}/${x}/${y}/2/1_1.png`;
}

/* OSM tile URL */
function osmTile(z, x, y) {
  const sub = ["a", "b", "c"][(x + y + z) % 3];
  return `https://${sub}.tile.openstreetmap.org/${z}/${x}/${y}.png`;
}

/* Lat/lon → tile coords */
function latLonToTile(lat, lon, z) {
  const x = Math.floor((lon + 180) / 360 * Math.pow(2, z));
  const latRad = lat * Math.PI / 180;
  const y = Math.floor((1 - Math.log(Math.tan(latRad) + 1 / Math.cos(latRad)) / Math.PI) / 2 * Math.pow(2, z));
  return { x, y };
}

/* Tile coord → pixel offset within a 3×3 grid centred on (cx, cy) */
function tileOffset(tx, ty, cx, cy, tileSize) {
  return { dx: (tx - cx) * tileSize, dy: (ty - cy) * tileSize };
}

const ZOOM = 6;
const TILE = 256;
const GRID = 5; // render 5×5 tiles around centre

function MapTiles({ lat, lon, radarPath, radarHost, opacity }) {
  const centre = latLonToTile(lat, lon, ZOOM);
  const half = Math.floor(GRID / 2);
  const tiles = [];

  for (let dy = -half; dy <= half; dy++) {
    for (let dx = -half; dx <= half; dx++) {
      const tx = centre.x + dx;
      const ty = centre.y + dy;
      const px = (dx + half) * TILE;
      const py = (dy + half) * TILE;

      tiles.push(
        <image
          key={`base-${tx}-${ty}`}
          href={osmTile(ZOOM, tx, ty)}
          x={px} y={py} width={TILE} height={TILE}
        />
      );

      if (radarPath) {
        tiles.push(
          <image
            key={`radar-${tx}-${ty}`}
            href={radarTile(radarHost, radarPath, ZOOM, tx, ty)}
            x={px} y={py} width={TILE} height={TILE}
            opacity={opacity}
          />
        );
      }
    }
  }

  /* sub-pixel offset so the city is exactly centred */
  const latRad = lat * Math.PI / 180;
  const n = Math.pow(2, ZOOM);
  const fracX = (lon + 180) / 360 * n - centre.x;
  const fracY = (1 - Math.log(Math.tan(latRad) + 1 / Math.cos(latRad)) / Math.PI) / 2 * n - centre.y;

  const totalSize = GRID * TILE;
  const viewSize = totalSize;
  const offsetX = -(fracX * TILE) + (viewSize / 2 - half * TILE);
  const offsetY = -(fracY * TILE) + (viewSize / 2 - half * TILE);

  return (
    <svg
      width="100%" height="100%"
      viewBox={`0 0 ${viewSize} ${viewSize}`}
      preserveAspectRatio="xMidYMid slice"
      style={{ position: "absolute", inset: 0 }}
    >
      <g transform={`translate(${offsetX}, ${offsetY})`}>
        {tiles}
      </g>
      {/* crosshair */}
      <circle cx={viewSize / 2} cy={viewSize / 2} r="6" fill="none" stroke="#fff" strokeWidth="2" opacity="0.9" />
      <circle cx={viewSize / 2} cy={viewSize / 2} r="2" fill="#fff" opacity="0.9" />
    </svg>
  );
}

function RadarScreen({ city, onClose }) {
  const [frames, setFrames] = React.useState([]);
  const [host, setHost] = React.useState("");
  const [frameIdx, setFrameIdx] = React.useState(0);
  const [playing, setPlaying] = React.useState(true);
  const [loading, setLoading] = React.useState(true);
  const [error, setError] = React.useState(false);
  const timerRef = React.useRef(null);

  /* fetch available radar frames — start paused on most recent frame */
  React.useEffect(() => {
    let alive = true;
    setLoading(true); setError(false);
    fetch(RAINVIEWER_API)
      .then(r => r.json())
      .then(data => {
        if (!alive) return;
        const h = data.host;
        const radar = data.radar?.past || [];
        if (!radar.length) { setError(true); return; }
        setHost(h);
        setFrames(radar);
        setFrameIdx(radar.length - 1);
        setPlaying(false);
        setLoading(false);
      })
      .catch(() => { if (alive) { setError(true); setLoading(false); } });
    return () => { alive = false; };
  }, []);

  /* animation loop — play forward from current frame */
  React.useEffect(() => {
    clearInterval(timerRef.current);
    if (!playing || frames.length === 0) return;
    timerRef.current = setInterval(() => {
      setFrameIdx(i => {
        const next = i + 1;
        if (next >= frames.length) { return 0; }
        return next;
      });
    }, 700);
    return () => clearInterval(timerRef.current);
  }, [playing, frames.length]);

  const currentFrame = frames[frameIdx];
  const frameTime = currentFrame ? new Date(currentFrame.time * 1000).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" }) : "";

  return (
    <div className="screen radar-screen fade-enter">
      {/* header */}
      <div className="radar-head">
        <button className="radar-back" onClick={onClose}>
          <svg width="11" height="18" viewBox="0 0 11 18" fill="none" stroke="#fff" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
            <path d="M9 1 1 9l8 8"/>
          </svg>
        </button>
        <div style={{ flex: 1 }}>
          <div className="radar-title">Radar</div>
          <div className="radar-sub">{city.name}</div>
        </div>
        {currentFrame && <div className="radar-time">{frameTime}</div>}
      </div>

      {/* map area */}
      <div className="radar-map">
        {loading && (
          <div className="radar-loader">
            <div className="ptr-spinner spin" style={{ animation: "spin 0.7s linear infinite", width: 32, height: 32 }} />
            <div style={{ marginTop: 14, color: "rgba(255,255,255,0.7)", fontSize: 14, fontWeight: 600 }}>Loading radar…</div>
          </div>
        )}
        {error && (
          <div className="radar-loader">
            <div style={{ fontSize: 32 }}>📡</div>
            <div style={{ marginTop: 12, color: "rgba(255,255,255,0.7)", fontSize: 14, fontWeight: 600 }}>Radar unavailable</div>
            <div style={{ marginTop: 4, color: "rgba(255,255,255,0.45)", fontSize: 12 }}>Check your connection</div>
          </div>
        )}
        {!loading && !error && (
          <MapTiles
            lat={city.lat} lon={city.lon}
            radarPath={currentFrame?.path}
            radarHost={host}
            opacity={0.7}
          />
        )}

        {/* dark overlay for contrast */}
        {!loading && !error && (
          <div style={{ position: "absolute", inset: 0, background: "rgba(0,0,0,0.18)", pointerEvents: "none" }} />
        )}
      </div>

      {/* controls */}
      {!loading && !error && frames.length > 0 && (
        <div className="radar-controls glass">
          {/* timeline scrubber */}
          <div className="radar-timeline">
            {frames.map((f, i) => (
              <button
                key={f.time}
                className={"radar-tick" + (i === frameIdx ? " active" : "")}
                onClick={() => { setFrameIdx(i); setPlaying(false); }}
              />
            ))}
          </div>

          {/* play/pause */}
          <button className="radar-play" onClick={() => setPlaying(p => !p)}>
            {playing ? (
              /* pause icon */
              <svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor">
                <rect x="5" y="3" width="4" height="18" rx="1.5"/><rect x="15" y="3" width="4" height="18" rx="1.5"/>
              </svg>
            ) : (
              /* play icon */
              <svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor">
                <path d="M6 4l14 8-14 8V4z"/>
              </svg>
            )}
          </button>

          <div className="radar-legend">
            <div className="radar-legend-bar" />
            <div className="radar-legend-labels">
              <span>Light</span><span>Heavy</span>
            </div>
          </div>
        </div>
      )}

      {/* attribution */}
      <div className="radar-attr">Map © OpenStreetMap · Radar © RainViewer</div>
    </div>
  );
}

window.RadarScreen = RadarScreen;
