<template>
  <div ref="arbitrateImgRef" class="arbitrate-img" @scroll="onImgScroll">
    <div class="arbitrate-img-box">
      <img ref="imgRef" :src="imgUri" alt="扫描结果" @load="onImgLoad" />
      <div class="img-recogs">
        <div class="recog-block is-active" :style="fillAreaStyle">
          <div
            v-for="(option, oindex) in fillOptionStyles"
            :key="oindex"
            :style="option"
            class="recog-item"
          ></div>
        </div>
      </div>
    </div>
  </div>
  <div ref="imgThumbRef" class="arbitrate-img-thumb">
    <img :src="imgUri" alt="扫描结果" />
    <div
      class="arbitrate-img-area"
      v-ele-move-directive.prevent.stop="{
        moveStart: moveAreaStart,
        moveElement: moveArea,
        moveStop: moveAreaStop,
      }"
      :style="areaStyle"
    ></div>
  </div>
</template>

<script setup lang="ts">
import { computed, ref, reactive, onMounted, nextTick, watch } from "vue";
import { vEleMoveDirective } from "@/directives/eleMove";
import { getFileUrl } from "@/utils/tool";
import { RecognizeArbitrateTaskDetail } from "@/ap/types/recognizeCheck";
import { useUserStore } from "@/store";

defineOptions({
  name: "RecognizeImage",
});

const props = defineProps<{
  recogData: RecognizeArbitrateTaskDetail;
}>();

const userStore = useUserStore();

const arbitrateImgRef = ref();
const imgRef = ref();

const imgUri = computed(() => {
  return getFileUrl(props.recogData.uri);
});

// img
function updateImgAreaSize() {
  const imgBoxDom = arbitrateImgRef.value as HTMLDivElement;
  const imgDom = imgBoxDom.firstChild as HTMLImageElement;
  const { clientHeight } = imgThumbRef.value as HTMLDivElement;

  const areaRate = Math.min(imgBoxDom.clientHeight / imgDom.clientHeight, 1);
  const areaHeight = clientHeight * areaRate;
  areaSize.height = areaHeight;
}

const fillAreaStyle = ref({} as Record<string, any>);
const fillOptionStyles = ref([] as Array<Record<string, any>>);
function updateRecogStyle() {
  const imgDom = imgRef.value as HTMLImageElement;
  const rate = imgDom.clientWidth / imgDom.naturalWidth;

  const { unfillColor, fillColor, borderWidth } = userStore.recogFillSet;
  const curBorderWidth = Math.max(1, borderWidth * rate);

  fillAreaStyle.value = {
    position: "absolute",
    left: `${props.recogData.fillArea.x * rate}px`,
    top: `${props.recogData.fillArea.y * rate}px`,
    width: `${props.recogData.fillArea.w * rate}px`,
    height: `${props.recogData.fillArea.h * rate}px`,
    zIndex: 9,
  };
  if (props.recogData.type !== "question") {
    fillOptionStyles.value = [];
    return;
  }

  fillOptionStyles.value = props.recogData.optionSizes.map((op) => {
    const opStyle = {
      position: "absolute",
      left: `${op.x * rate}px`,
      top: `${op.y * rate}px`,
      width: `${op.w * rate}px`,
      height: `${op.h * rate}px`,
      zIndex: 9,
      border: "",
    };

    if (op.filled) {
      opStyle.border = `${curBorderWidth}px solid ${fillColor}`;
    } else {
      opStyle.border = `${curBorderWidth}px solid ${unfillColor}`;
    }

    return opStyle;
  });
}

function onImgLoad() {
  updateImgAreaSize();

  nextTick(() => {
    updateRecogStyle();
  });
}

watch(
  () => props.recogData,
  (val, oldval) => {
    if (val && oldval && val.uri === oldval.uri) {
      updateRecogStyle();
    }
  }
);

let areaIsMoving = false;
function onImgScroll(e: Event) {
  if (areaIsMoving) {
    e.preventDefault();
    return;
  }

  const imgBoxDom = arbitrateImgRef.value as HTMLDivElement;
  if (!imgBoxDom) return;
  const scrollTop = imgBoxDom.scrollTop;
  const imgDom = imgBoxDom.firstChild as HTMLImageElement;
  const { clientHeight } = imgThumbRef.value as HTMLDivElement;
  areaSize.top = (clientHeight * scrollTop) / imgDom.clientHeight;
}

// img-thumb area
const imgThumbRef = ref();
const areaSize = reactive({
  height: 40,
  top: 0,
});
const areaOriginTop = ref(0);

const areaStyle = computed(() => {
  return { height: `${areaSize.height}px`, top: `${areaSize.top}px` };
});
interface MovePos {
  left: number;
  top: number;
}

function moveAreaStart() {
  areaOriginTop.value = areaSize.top;
  areaIsMoving = false;
}
function moveArea(pos: MovePos) {
  areaIsMoving = true;
  const areaTop = pos.top + areaOriginTop.value;
  const { clientHeight } = imgThumbRef.value as HTMLDivElement;
  areaSize.top = Math.min(areaTop, clientHeight - areaSize.height);
  areaSize.top = Math.max(0, areaSize.top);

  const imgBoxDom = arbitrateImgRef.value as HTMLDivElement;
  const imgDom = imgBoxDom.firstChild as HTMLImageElement;
  imgBoxDom.scrollTop = (imgDom.clientHeight * areaSize.top) / clientHeight;
}

function moveAreaStop(pos: MovePos) {
  moveArea(pos);
  areaIsMoving = false;
}
</script>

<style lang="less" scoped>
.arbitrate-img {
  .recog-block {
    &:hover {
      background-color: rgba(241, 214, 110, 0.3);
    }
    &.is-active {
      background-color: rgba(241, 214, 110, 0.3);
      &::after {
        content: "";
        display: block;
        position: absolute;
        z-index: 1;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        border: 1px dashed #000;
      }
    }
  }
}
</style>
