<script lang="ts" context="module">
  import { writable } from "svelte/store";
  import api from "../lib/api";

  export const selected = writable<string[]>([]);
  export async function selectGroup(address: string) {
    const result = await api.query(
      new Query().matches(undefined, ATTR_IN, `@${address}`),
    );
    result.entities
      .map((e) => e.replace(/^@/, ""))
      .forEach((entity) => {
        selected.update((selected) => {
          if (!selected.includes(entity)) {
            return [...selected, entity];
          } else {
            return selected;
          }
        });
      });
  }
</script>

<script lang="ts">
  import { onMount } from "svelte";
  import { i18n } from "../i18n";

  import { Query } from "@upnd/upend";
  import { ATTR_IN } from "@upnd/upend/constants";

  let canvas: HTMLCanvasElement;

  onMount(() => {
    const ctx = canvas.getContext("2d");

    function resizeCanvas() {
      canvas.width = window.innerWidth;
      canvas.height = window.innerHeight;
    }
    window.addEventListener("resize", resizeCanvas);
    resizeCanvas();

    let selecting = false;
    let selectAllArea: DOMRect | undefined = undefined;
    let selectAllAddress: string | undefined = undefined;
    let addressesToRemove = new Set();
    document.addEventListener("mousedown", (ev) => {
      if (ev.ctrlKey) {
        ev.preventDefault();

        selecting = true;
        addressesToRemove = new Set();

        const el = document.elementFromPoint(
          ev.clientX,
          ev.clientY,
        ) as HTMLElement;

        const groupElement = el.closest("[data-address-group]") as
          | HTMLElement
          | undefined;

        if (groupElement) {
          const banner = groupElement.querySelector("h2 .banner");

          if (banner) {
            const rect = banner.getBoundingClientRect();
            selectAllArea = rect;
            selectAllAddress = groupElement.dataset.addressGroup;

            ctx.rect(rect.left, rect.top, rect.width, rect.height);
            ctx.fillStyle = "#dc322f33";
            ctx.fill();

            ctx.fillStyle = "#dc322f77";
            ctx.font = `bold ${rect.height / 2}px Inter`;
            ctx.textAlign = "center";
            ctx.textBaseline = "middle";
            const fix = ctx.measureText("M").actualBoundingBoxDescent / 2;
            ctx.fillText(
              $i18n.t("Select All"),
              rect.left + rect.width / 2,
              rect.top + rect.height / 2 + fix,
            );
          }
        }

        ctx.strokeStyle = "#dc322f77";
        ctx.lineWidth = 7;
        ctx.beginPath();
        ctx.moveTo(ev.clientX, ev.clientY);
      }
    });

    document.addEventListener("mousemove", (ev) => {
      if (selecting) {
        ev.preventDefault();

        if (selectAllArea) {
          if (
            ev.clientX > selectAllArea.left &&
            ev.clientX < selectAllArea.right &&
            ev.clientY > selectAllArea.top &&
            ev.clientY < selectAllArea.bottom
          ) {
            selectGroup(selectAllAddress);
            stop();
          }
        }

        const el = document.elementFromPoint(
          ev.clientX,
          ev.clientY,
        ) as HTMLElement;

        const addressElement = el.closest("[data-address]") as
          | HTMLElement
          | undefined;
        if (addressElement) {
          const address = addressElement.dataset.address;
          const selectMode = addressElement.dataset.selectMode;
          if (selectMode === "add" || selectMode === undefined) {
            selected.update((selected) => {
              if (!selected.includes(address)) {
                return [...selected, address];
              } else {
                return selected;
              }
            });
          } else if (selectMode === "remove") {
            addressesToRemove.add(address);
          }
        }

        ctx.lineTo(ev.clientX, ev.clientY);
        ctx.stroke();
        ctx.beginPath();
        ctx.moveTo(ev.clientX, ev.clientY);
      }
    });

    document.addEventListener("mouseup", () => {
      stop();
    });

    function stop() {
      selectAllArea = undefined;
      selectAllAddress = undefined;
      selecting = false;
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      for (const address of addressesToRemove) {
        selected.update((selected) => {
          return selected.filter((a) => a !== address);
        });
      }
    }
  });
</script>

<div class="selectIndicator">
  <canvas bind:this={canvas}></canvas>
</div>

<style lang="scss">
  .selectIndicator {
    position: absolute;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;

    pointer-events: none;

    canvas {
      width: 100%;
      height: 100%;
    }
  }
</style>
