<script>
  import { onMount } from 'svelte';
  import { Canvas } from 'svelte-canvas';
  import { extent } from 'd3-array';
  import { scaleLinear } from 'd3-scale';
  import { Delaunay } from 'd3-delaunay';

  import Point from './Point.svelte';
  import Axis from './Axis.svelte';

  const margin = { top: 24, right: 24, bottom: 36, left: 36 };

  let points = $state([]),
    width = $state(),
    height = $state(),
    picked = $state(null),
    click = $state(false);

  onMount(() =>
    fetch(
      'https://raw.githubusercontent.com/vega/vega/master/docs/data/cars.json',
    )
      .then((data) => data.json())
      .then((data) => {
        points = data
          .map((d, id) => ({ mpg: d.Miles_per_Gallon, hp: d.Horsepower, id }))
          .filter((d) => d.mpg && d.hp);
      }),
  );

  let x = $derived(
    scaleLinear()
      .domain(extent(points, (d) => d.mpg))
      .range([margin.left, width - margin.right])
      .nice(),
  );

  let y = $derived(
    scaleLinear()
      .domain(extent(points, (d) => d.hp))
      .range([height - margin.bottom, margin.top])
      .nice(),
  );

  let delaunay = $derived(
    Delaunay.from(
      points,
      (d) => x(d.mpg),
      (d) => y(d.hp),
    ),
  );
</script>

<Canvas
  style="cursor: pointer"
  onresize={(e) => {
    width = e.width;
    height = e.height;
  }}
  onmousemove={({ offsetX, offsetY }) => {
    const i = delaunay.find(offsetX, offsetY);
    if (i) {
      picked = points[i].id;
      points.push(points.splice(i, 1)[0]);
      points = points;
    }
  }}
  onmouseout={() => (picked = null)}
  onmousedown={() => (click = true)}
  onmouseup={() => (click = false)}
>
  <Axis type="x" scale={x} tickNumber={8} {margin} />
  <Axis type="y" scale={y} tickNumber={10} {margin} />
  {#each points as { mpg, hp, id } (id)}
    <Point
      x={x(mpg)}
      y={y(hp)}
      fill="tomato"
      r={id === picked && !click ? 5 : 3}
      stroke={id === picked ? '#eee' : null}
    />
  {/each}
</Canvas>