<template>
  <svg
    xmlns="http://www.w3.org/2000/svg"
    viewBox="0 0 1000 1000"
    preserveAspectRatio="none"
    @mousedown.left="draw_start"
    @mouseup.left="draw_finish"
    @contextmenu.prevent
    @mousedown.right="drag_start"
    @mouseup.right="drag_finish"
    @mousemove="on_mousemove"
    @click.middle="remove_rect"
    @dblclick.left="remove_rect"
  >
    <Rect
      v-for="(rect, index) in rectangles"
      :key="'rect' + index"
      :rectangle="rect"
    />
    <Rect
      v-if="preview_visible"
      :focused="true"
      :rectangle="preview_rectangle"
    />
  </svg>
</template>

<script lang="ts">
import { Vue, Options } from "vue-class-component";
import { Vector2D, Rectangle } from "./rectangles";
import Rect from "./Rect.vue";

function get_event_thous(event: MouseEvent): Vector2D {
  if (event.currentTarget === null) {
    return new Vector2D();
  }

  const target = event.currentTarget as Element;

  return new Vector2D(
    Math.round((event.offsetX / target.clientWidth) * 1000),
    Math.round((event.offsetY / target.clientHeight) * 1000)
  );
}

@Options({
  components: {
    Rect,
  },
})
export default class RectPad extends Vue {
  private readonly min_rect_area = 4;
  private drawing = false;
  private preview_corner1 = new Vector2D();
  private preview_corner2 = new Vector2D();
  private dragging = false;
  private drag_rect?: Rectangle;
  private drag_origin = new Vector2D();
  private rectangles: Rectangle[] = [];

  private get preview_visible(): boolean {
    return this.drawing || this.dragging;
  }

  private get preview_rectangle(): Rectangle {
    return new Rectangle(
      this.preview_corner1,
      this.preview_corner2
    ).normalize();
  }

  private pop_rectangle(point: Vector2D): Rectangle | undefined {
    const idx = this.rectangles.findIndex((rect) => rect.contains(point));

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

    return this.rectangles.splice(idx, 1)[0];
  }

  private draw_start(event: MouseEvent) {
    if (this.preview_visible) {
      return;
    }

    this.drawing = true;
    this.preview_corner1 = get_event_thous(event);
    this.preview_corner2 = get_event_thous(event);
  }

  private draw_finish() {
    if (!this.drawing) {
      return;
    }

    this.drawing = false;

    if (this.preview_rectangle.area < this.min_rect_area) {
      return;
    }

    this.rectangles.push(this.preview_rectangle);
  }

  private drag_start(event: MouseEvent) {
    if (this.preview_visible) {
      return;
    }

    const point = get_event_thous(event);
    this.drag_rect = this.pop_rectangle(point);

    if (this.drag_rect === undefined) {
      return;
    }

    this.dragging = true;
    this.drag_origin = point;

    this.preview_corner1 = this.drag_rect.origin;
    this.preview_corner2 = this.drag_rect.corner;
  }

  private drag_finish() {
    if (!this.dragging) {
      return;
    }

    this.dragging = false;
    this.rectangles.push(this.preview_rectangle);
  }

  private on_mousemove(event: MouseEvent) {
    if (this.drawing) {
      this.preview_corner2 = get_event_thous(event);
    } else if (this.dragging && this.drag_rect) {
      const movement = get_event_thous(event).minus(this.drag_origin);

      this.preview_corner1 = this.drag_rect.origin.plus(movement);
      this.preview_corner2 = this.drag_rect.corner.plus(movement);
    }
  }

  private remove_rect(event: MouseEvent) {
    this.pop_rectangle(get_event_thous(event));
  }
}
</script>

<style scoped>
svg {
  cursor: crosshair;
}
</style>