<template>
  <ThouCanvas
    @mousedown.left="draw_start"
    @mouseup.left="draw_finish"
    @mousedown.right="drag_start"
    @mouseup.right="drag_finish"
    @mousemove="on_mousemove"
    @click.middle="remove_rect"
    @dblclick.left="remove_rect"
  >
    <CalendarDoor
      v-for="(door, index) in model"
      :key="`door-${index}`"
      :door="door"
      force_visible
    />
    <SVGRect
      v-if="state.kind !== 'idle'"
      variant="success"
      :rectangle="preview"
      visible
    />
  </ThouCanvas>
</template>

<script setup lang="ts">
import { Door } from "@/lib/rects/door";
import { Rectangle } from "@/lib/rects/rectangle";
import { Vector2D } from "@/lib/rects/vector2d";

import CalendarDoor from "../calendar/CalendarDoor.vue";
import SVGRect from "../calendar/SVGRect.vue";
import ThouCanvas from "../calendar/ThouCanvas.vue";

type CanvasState =
  | { kind: "idle" }
  | { kind: "drawing" }
  | { kind: "dragging"; door: Door; origin: Vector2D };

const model = defineModel<Door[]>({ required: true });

const MIN_RECT_AREA = 300;
let state: CanvasState = { kind: "idle" };
let preview = new Rectangle();

function pop_door(point: Vector2D): Door | undefined {
  const idx = model.value.findIndex((rect) => rect.position.contains(point));

  if (idx === -1) {
    return;
  }

  return model.value.splice(idx, 1)[0];
}

function draw_start(event: MouseEvent, point: Vector2D) {
  if (state.kind !== "idle") {
    return;
  }

  preview = new Rectangle(point, point);
  state = { kind: "drawing" };
}

function draw_finish() {
  if (state.kind !== "drawing" || preview.area < MIN_RECT_AREA) {
    return;
  }

  model.value.push(new Door(preview));

  state = { kind: "idle" };
}

function drag_start(event: MouseEvent, point: Vector2D) {
  if (state.kind !== "idle") {
    return;
  }

  const drag_door = pop_door(point);

  if (drag_door === undefined) {
    return;
  }

  preview = drag_door.position;

  state = { kind: "dragging", door: drag_door, origin: point };
}

function drag_finish() {
  if (state.kind !== "dragging") {
    return;
  }

  model.value.push(new Door(preview, state.door.day));

  state = { kind: "idle" };
}

function on_mousemove(event: MouseEvent, point: Vector2D) {
  if (state.kind === "drawing") {
    preview = preview.update(undefined, point);
  } else if (state.kind === "dragging") {
    const movement = point.minus(state.origin);
    preview = state.door.position.move(movement);
  }
}

function remove_rect(event: MouseEvent, point: Vector2D) {
  if (state.kind !== "idle") {
    return;
  }

  pop_door(point);
}
</script>

<style lang="scss" scoped>
svg {
  cursor: crosshair;

  * {
    pointer-events: none;
  }
}
</style>
