<script>
  import { onMount, onDestroy } from "svelte";

  import Navbar from "./Navbar.svelte";
  import Mask from "./Mask.svelte";
  import { ImageProcess } from "./utils";

  const cv = window.cv;
  let image_process = new ImageProcess();

  export let url = "test.jpg";

  let canvas_dom;
  let resize_tag;
  let image;

  let image_for_show;
  let window_width;
  let window_height;
  let canvas_width = 0;
  let canvas_height = 0;

  let mask_tag = false;
  let crop_rect = {};

  function LabelItem(label, items) {
    this.label = label;

    this.items = items.map((e) => {
      return new OperationItem(e[0], e[1], e[2]);
    });
  }

  function OperationItem(name, icon, handler = null) {
    this.name = name;
    this.icon = icon;
    this.handler = handler;
  }

  const Menu = [
    new LabelItem("采集操作", [
      ["确认并返回", "mdi mdi-checkbox-marked-circle-outline"],
      ["重新采集", "mdi mdi-reply-outline"],
    ]),
    new LabelItem("图像操作", [
      [
        "向左旋转",
        "mdi mdi-file-rotate-left-outline",
        () => {
          image_process.turn_left();
          cv.rotate(image_for_show, image_for_show, 0);
          show_image();
        },
      ],
      [
        "向右旋转",
        "mdi mdi-file-rotate-right-outline",
        () => {
          image_process.turn_right();
          cv.rotate(image_for_show, image_for_show, 2);
          show_image();
        },
      ],
      ["文本加强", "mdi mdi-image-filter-center-focus-strong"],
      [
        "裁剪",
        "mdi mdi-crop",
        () => {
          image_process.roi_init();
          show_image();
          mask_tag = mask_tag ? false : true;
        },
      ],
      [
        "还原",
        "mdi mdi-alpha-x-circle-outline",
        () => {
          image_process.recover();
          init_canvas();
        },
      ],
    ]),
    new LabelItem("文件操作", [
      ["保存到本地", "mdi mdi-content-save-outline"],
      ["打印图片", "mdi mdi-printer-outline"],
    ]),
  ];

  $: {
    canvas_height = window_height - 64;
    canvas_width = window_width * 0.8125;
  }

  function on_window_resize() {
    if (resize_tag) {
      clearTimeout(resize_tag);
    }
    resize_tag = setTimeout(function () {
      image_process.roi_init();
      if (image) {
        let pre_scale = Math.min(
          canvas_height / image.rows,
          canvas_width / image.cols
        );
        let pre_dsize = new cv.Size(
          pre_scale * image.cols,
          pre_scale * image.rows
        );
        cv.resize(
          image_for_show,
          image_for_show,
          pre_dsize,
          0,
          0,
          cv.INTER_AREA
        );

        show_image();
      }
    }, 40);
  }

  function show_image() {
    mask_tag = false;
    let dst = new cv.Mat();
    console.time("image show");
    if (image_process.roi_tag) {
      dst = image_for_show.roi(image_process.ROI_rect);
    } else {
      dst = image_for_show.clone();
    }

    let scale = Math.min(canvas_height / dst.rows, canvas_width / dst.cols);
    let dsize = new cv.Size(scale * dst.cols, scale * dst.rows);
    cv.resize(dst, dst, dsize, 0, 0, cv.INTER_AREA);

    cv.imshow("canvas", dst);

    console.timeEnd("image show");
    dst.delete();
  }

  async function init_canvas() {
    let img = new Image();
    image_for_show = new cv.Mat();
    img.src = url;
    img.onload = function () {
      setTimeout(() => {
        image = cv.imread(img);
        let pre_scale = Math.min(
          canvas_height / image.rows,
          canvas_width / image.cols
        );
        let pre_dsize = new cv.Size(
          pre_scale * image.cols,
          pre_scale * image.rows
        );
        cv.resize(image, image_for_show, pre_dsize, 0, 0, cv.INTER_AREA);

        show_image();
      }, 50);
    };
  }

  function wheel_event_handler(e) {
    e.preventDefault();
    let mouse_point = new cv.Point(
      e.clientX - canvas_dom.offsetLeft,
      e.clientY - canvas_dom.offsetTop
    );
    image_process.roi(
      image_for_show.rows,
      image_for_show.cols,
      mouse_point,
      e.deltaY
    );
    show_image();
  }

  function keyboard_move_roi(event) {
    if (event.shiftKey && event.altKey && event.ctrlKey) {
      return;
    }
    if (event.keyCode > 40 || event.keyCode < 37) {
      return;
    }
    event.preventDefault();
    switch (event.key) {
      case "ArrowUp":
        image_process.roi_up();
        break;
      case "ArrowDown":
        image_process.roi_down(image_for_show.rows);
        break;
      case "ArrowLeft":
        image_process.roi_left();
        break;
      case "ArrowRight":
        image_process.roi_right(image_for_show.cols);
        break;
    }
    show_image();
  }

  /*function mouse_move_roi(event) {
    if (event.type == "mousedown") {
      roi_move_tag = true;
    } else if (event.type == "mouseup") {
      roi_move_tag = false;
    }
  }

  function drag_roi(event) {
    if (roi_move_tag) {
      console.log(event);
      let delta = {
        x: event.clientX - mouse_move.x,
        y: event.clientY - mouse_move.y,
      };
      image_process.roi_move(delta);
      mouse_move = {
        x: event.clientX,
        y: event.clientY,
      };
      show_image();
    }
  }*/

  onMount(async () => {
    canvas_height = window_height - 64;
    canvas_width = (window_width * 13) / 16;
    init_canvas();
  });

  onDestroy(async () => {
    if (image.delete) {
      image.delete();
    }
    if (image_for_show.delete) {
      image_for_show.delete();
    }
  });
</script>

<svelte:window
  bind:innerHeight={window_height}
  bind:innerWidth={window_width}
  on:resize={on_window_resize}
  on:keydown={keyboard_move_roi}
/>

<div class="disable-selection">
  <Navbar />
  <div class="columns is-gapless">
    <div class="column is-2" style="margin: 10px">
      <aside class="menu">
        {#each Menu as m}
          <p class="menu-label" style="font-size: 0.9em">{m.label}</p>
          <ul class="menu-list">
            {#each m.items as item}
              <!-- svelte-ignore a11y-missing-attribute -->
              <!-- svelte-ignore a11y-click-events-have-key-events -->
              <li>
                <a
                  on:click={() => {
                    if (item.handler) {
                      item.handler();
                    }
                  }}
                  ><span class="icon-text">
                    <span class="icon">
                      <i class={item.icon} />
                    </span><span> {item.name}</span></span
                  >
                </a>
              </li>
            {/each}
          </ul>
        {/each}
      </aside>
    </div>
    <div class="column" style="text-align:center">
      <div>
        {#if mask_tag}
          <Mask
            {canvas_dom}
            on:maskclose={(e) => {
              mask_tag = false;
              console.log(e);
            }}
          />
        {/if}
        <canvas
          bind:this={canvas_dom}
          id="canvas"
          on:wheel={wheel_event_handler}
        />
      </div>
    </div>
  </div>
</div>

<style>
  canvas {
    border: 1px solid black;
  }
</style>
