<template>
  <div class="image">
    <div class="canvas">
      <canvas
        width="1300"
        height="800"
        id="canvas"
        :style="{
          transform: `scale(${scale}) rotate(${rotationAngle}deg)`,
          transition: 'transform 0.2s',
        }"
      ></canvas>
    </div>

    <div class="bottom">
      <div class="buttonList">
        <!-- 放大 -->
        <div class="button"> <ZoomInOutlined @click="zoomIn" /> </div>
        <!-- 缩小 -->
        <div class="button"> <ZoomOutOutlined @click="zoomOut" /> </div>
        <!-- 顺时针旋转 -->
        <div class="button"> <RotateRightOutlined @click="rotateClockwise" /> </div>
        <!-- 逆时针旋转 -->
        <div class="button"> <RotateLeftOutlined @click="rotateCounterClockwise" /> </div>
        |
        <!-- 刷新 -->
        <div class="button"> <RedoOutlined @click="refreshCanvas" /> </div>
        <!-- 涂鸦 -->
        <div class="tipChoose" v-if="graffitiFlag">
          <n-color-picker size="small" :modes="['rgb']" v-model:value="graffitiColor" />
          <a-slider v-model:value="graffitiWidth" :min="1" :max="10" />
        </div>
        <div class="button" :style="{ background: graffitiFlag ? 'blue' : '' }">
          <HighlightOutlined
            :style="{
              color: graffitiColor,
            }"
            @click="
              graffitiFlag = !graffitiFlag;
              rectFlag = false;
              textboxFlag = false;
            "
          />
        </div>
        <!-- 标注 -->
        <div class="tipChoose" v-if="rectFlag">
          <n-color-picker size="small" :modes="['rgb']" v-model:value="rectColor" />
        </div>
        <div class="button" :style="{ background: rectFlag ? 'blue' : '' }">
          <BorderOutlined
            @click="
              graffitiFlag = false;
              rectFlag = !rectFlag;
              textboxFlag = false;
            "
          />
        </div>
        <!-- 文字 -->
        <div class="tipChoose" v-if="textboxFlag">
          <n-color-picker size="small" :modes="['rgb']" v-model:value="textboxColor" />
          <a-slider v-model:value="textboxFontSize" :min="10" :max="50" />
        </div>
        <div class="button" :style="{ background: textboxFlag ? 'blue' : '' }">
          <FontSizeOutlined
            @click="
              graffitiFlag = false;
              rectFlag = false;
              textboxFlag = !textboxFlag;
            "
          />
        </div>
        <!-- 保存 -->
        <div class="button"> <CheckOutlined @click="checkCanvas" /> </div>
        <!-- 删除 -->
        <div class="button"> <CloseOutlined @click="deleteCanvas" /> </div>
        <!-- 隐藏or显示涂鸦和标签 -->
        <div class="button">
          <EyeOutlined @click="hideOrShowGraffiti(false)" v-if="hideOrShowGraffitiFlag" />
          <EyeInvisibleOutlined @click="hideOrShowGraffiti(true)" v-if="!hideOrShowGraffitiFlag" />
          <div style="position: absolute; bottom: 0px; right: 0px; font-size: 10px">涂鸦</div>
        </div>
        <div class="button">
          <EyeOutlined @click="hideOrShowTextbox(false)" v-if="hideOrShowTextboxFlag" />
          <EyeInvisibleOutlined @click="hideOrShowTextbox(true)" v-if="!hideOrShowTextboxFlag" />
          <div style="position: absolute; bottom: 0px; right: 0px; font-size: 10px">标签</div>
        </div>
        |
        <!-- 复制到剪贴板 -->
        <div class="button">
          <ExportOutlined @click="copyToClipboard(props.nowPreviewRecord.url)" />
        </div>
        <!-- 下载 -->
        <div class="button">
          <DownloadOutlined @click="fetchAndDownloadImage(props.nowPreviewRecord.url)" />
        </div>
      </div>
      <div class="imageList">
        <div v-for="li in props.previewRecordList" :key="li.id" @click="chooseNowPreviewRecord(li)">
          <div
            :class="li.id == props.nowPreviewRecord.id ? 'bottom_div_choose' : 'bottom_div'"
            v-if="li.type == 'img'"
          >
            <img :src="li.url" :width="60" :height="40" />
          </div>
        </div>
      </div>
    </div>

    <div class="leftButton" @click="clickLeftOrRightButton('left')">
      <LeftOutlined style="color: #ffffff; font-size: 20px" />
    </div>
    <div class="rightButton" @click="clickLeftOrRightButton('right')">
      <RightOutlined style="color: #ffffff; font-size: 20px" />
    </div>
  </div>
</template>
<script lang="ts" setup>
  import { ref, onMounted, watch, computed } from 'vue';
  import { fabric } from 'fabric';
  import {
    CloseOutlined,
    RightOutlined,
    LeftOutlined,
    ZoomOutOutlined,
    ZoomInOutlined,
    RotateLeftOutlined,
    RotateRightOutlined,
    RedoOutlined,
    FileImageOutlined,
    ExportOutlined,
    DownloadOutlined,
    DeleteOutlined,
    HighlightOutlined,
    CheckOutlined,
    FontSizeOutlined,
    BorderOutlined,
    EyeOutlined,
    EyeInvisibleOutlined,
  } from '@ant-design/icons-vue';
  import { useMessage } from '@/hooks/web/useMessage';
  import { json } from 'stream/consumers';

  const { createConfirm, createMessage } = useMessage();

  const props = defineProps(['nowPreviewRecord', 'previewRecordList']);
  const emit = defineEmits(['chooseNowPreviewRecord', 'reloadTable']);

  // 上一张、下一张图片
  function clickLeftOrRightButton(direction) {
    const list = props.previewRecordList.filter((item) => item.type == 'img');
    for (let index = 0; index < list.length; index++) {
      if (list[index].id == props.nowPreviewRecord.id) {
        if (direction == 'left') {
          if (index == 0) {
            chooseNowPreviewRecord(list[list.length - 1]);
          } else {
            chooseNowPreviewRecord(list[index - 1]);
          }
        }
        if (direction == 'right') {
          if (index == list.length - 1) {
            chooseNowPreviewRecord(list[0]);
          } else {
            chooseNowPreviewRecord(list[index + 1]);
          }
        }
      }
    }
  }

  // 选择
  function chooseNowPreviewRecord(value) {
    emit('chooseNowPreviewRecord', value);
    // 初始化
    scale.value = 1;
    rotationAngle.value = 0;
    setBackgroudUrl(value);
  }

  // 刷新表格
  function reloadTable() {
    emit('reloadTable');
  }

  // 画布
  const nowCanvasJson = ref(props.nowPreviewRecord.canvasJson);
  let canvas: any = null;

  // 设置背景图
  function setBackgroudUrl(value) {
    nowCanvasJson.value = value.canvasJson;
    canvas.loadFromJSON(value.canvasJson);
    fabric.Image.fromURL(value.url, (img) => {
      // 设置背景图
      canvas.setBackgroundImage(img, canvas.renderAll.bind(canvas), {
        scaleX: canvas.width / img.width,
        scaleY: canvas.height / img.height,
      });
    });
  }

  // 设置画笔---------------------------------------------------------------
  const graffitiFlag = ref(false);
  const graffitiColor = ref('#ffffff');
  const graffitiWidth = ref(1);

  watch(
    () => (graffitiFlag.value, graffitiColor.value, graffitiWidth.value),
    () => {
      setGraffiti();
    },
    {
      deep: true,
    },
  );
  // 设置画笔
  function setGraffiti() {
    scale.value = 1;
    rotationAngle.value = 0;
    // 设置画笔开启
    canvas.isDrawingMode = graffitiFlag.value;
    // 设置画笔颜色
    canvas.freeDrawingBrush.color = graffitiColor.value;
    // 设置画笔粗细
    canvas.freeDrawingBrush.width = graffitiWidth.value;
  }

  // 设置文本---------------------------------------------------------------
  const textboxFlag = ref(false);
  const textboxColor = ref('#ffffff');
  const textboxFontSize = ref(20);

  watch(
    () => textboxFlag.value,
    () => {
      if (textboxFlag.value) {
        setTextbox();
      }
    },
    {
      deep: true,
    },
  );
  watch(
    () => (textboxColor.value, textboxFontSize.value),
    () => {
      setTextboxStyle();
    },
    {
      deep: true,
    },
  );

  // 新增文本
  function setTextbox() {
    scale.value = 1;
    rotationAngle.value = 0;
    addClickEvent();
  }
  // 设置文本样式
  function setTextboxStyle() {
    const activeObj = canvas.getActiveObject();
    if (activeObj) {
      console.log(activeObj);
      activeObj.fill = textboxColor.value;
      activeObj.fontSize = textboxFontSize.value;
      canvas.setActiveObject(activeObj);
    }
  }

  // 设置矩形---------------------------------------------------------------
  const rectFlag = ref(false);
  const rectColor = ref('#ffffff');

  watch(
    () => rectFlag.value,
    () => {
      if (rectFlag.value) {
        setRect();
      }
    },
    {
      deep: true,
    },
  );
  watch(
    () => rectColor.value,
    () => {
      setRectStyle();
    },
    {
      deep: true,
    },
  );

  // 新增矩形
  function setRect() {
    scale.value = 1;
    rotationAngle.value = 0;
    addClickEvent();
  }
  // 设置矩形样式
  function setRectStyle() {
    const activeObj = canvas.getActiveObject();
    if (activeObj) {
      activeObj.stroke = rectColor.value;
      canvas.setActiveObject(activeObj);
    }
  }

  // 添加画布点击事件
  function addClickEvent() {
    canvas.on('mouse:down', (options) => {
      if (textboxFlag.value) {
        // 将文本框添加到画布中
        const textbox = new fabric.Textbox('标注', {
          width: 200,
          fill: textboxColor.value,
          fontSize: textboxFontSize.value,
          top: options.absolutePointer.y,
          left: options.absolutePointer.x,
        });
        canvas.add(textbox);
        removeClickEvent();
      }
      if (rectFlag.value) {
        // 将矩形添加到画布中
        const rect = new fabric.Rect({
          top: options.absolutePointer.y,
          left: options.absolutePointer.x,
          fill: '#ffffff00',
          stroke: rectColor.value,
          width: 100,
          height: 100,
        });
        canvas.add(rect);
        removeClickEvent();
      }
    });
  }
  // 移除画布点击事件
  function removeClickEvent() {
    canvas.off('mouse:down');
  }

  // 缩放比例-----------------------------------
  const scale = ref(1);
  // 放大函数
  function zoomIn() {
    if (scale.value < 3) {
      // 设置最大缩放倍数为3倍
      scale.value += 0.1;
    }
  }
  // 缩小函数
  function zoomOut() {
    if (scale.value > 0.5) {
      // 设置最小缩放倍数为0.5倍
      scale.value -= 0.1;
    }
  }

  // 旋转-----------------------------------
  const rotationAngle = ref(0);
  // 顺时针旋转函数
  function rotateClockwise() {
    rotationAngle.value += 90; // 每次旋转90度
  }
  // 逆时针旋转
  function rotateCounterClockwise() {
    rotationAngle.value -= 90; // 每次旋转-90度
  }

  // 保存-----------------------------------
  function checkCanvas() {
    nowCanvasJson.value = JSON.stringify(canvas);
    props.nowPreviewRecord.canvasJson = JSON.stringify(canvas);
    textboxFlag.value = false;
    graffitiFlag.value = false;
    rectFlag.value = false;
    console.log(JSON.stringify(canvas));
    createMessage.success('保存成功！');
  }

  // 删除
  function deleteCanvas() {
    const activeObj = canvas.getActiveObject();
    canvas.remove(activeObj);
    textboxFlag.value = false;
    graffitiFlag.value = false;
    rectFlag.value = false;
  }

  // 刷新
  function refreshCanvas() {
    scale.value = 1;
    rotationAngle.value = 0;
    setBackgroudUrl(props.nowPreviewRecord);
  }

  // 复制到剪贴板-----------------------------------
  const copyToClipboard = async (url) => {
    try {
      await navigator.clipboard.writeText(url);
      createMessage.success('图片链接已复制到剪贴板');
    } catch (err) {
      createMessage.error('无法复制图片链接');
    }
  };

  // 下载
  async function fetchAndDownloadImage(url) {
    try {
      const response = await fetch(url, {
        mode: 'cors',
      });
      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }
      const blob = await response.blob();
      const urlObject = window.URL.createObjectURL(blob);
      const link = document.createElement('a');
      link.href = urlObject;
      link.download = props.nowPreviewRecord.name;
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
      window.URL.revokeObjectURL(urlObject);
    } catch (error) {
      console.error('Error downloading image:', error);
    }
  }

  // 隐藏涂鸦
  const hideOrShowGraffitiFlag = ref(true);
  function hideOrShowGraffiti(value) {
    hideOrShowGraffitiFlag.value = value;
    let json = JSON.parse(nowCanvasJson.value);
    json.objects.forEach((item) => {
      if (item.type === 'path') {
        item.visible = value;
      }
    });
    nowCanvasJson.value = JSON.stringify(json);
    canvas.loadFromJSON(nowCanvasJson.value);
  }

  // 隐藏标签
  const hideOrShowTextboxFlag = ref(true);
  function hideOrShowTextbox(value) {
    hideOrShowTextboxFlag.value = value;
    let json = JSON.parse(nowCanvasJson.value);
    json.objects.forEach((item) => {
      if (item.type === 'textbox' || item.type === 'rect') {
        item.visible = value;
      }
    });
    nowCanvasJson.value = JSON.stringify(json);
    canvas.loadFromJSON(nowCanvasJson.value);
  }

  onMounted(() => {
    canvas = new fabric.Canvas('canvas');
    // 背景图片
    setBackgroudUrl(props.nowPreviewRecord);
    // json
    if (!nowCanvasJson.value) {
      nowCanvasJson.value = JSON.stringify(canvas);
    }
    // 涂鸦
    setGraffiti();
  });
</script>
<style lang="less" scoped>
  .image {
    position: relative;
    width: 100%;
    height: 900px;
    display: block;
  }

  .canvas {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 800px;
  }

  .bottom {
    position: absolute;
    bottom: 0px;
    left: 0px;
    width: 100%;
    height: 100px;
    background: #1c1c1c;
    display: block;

    .buttonList {
      position: relative;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 100%;
      height: 40px;

      .button {
        position: relative;
        padding-left: 10px;
        padding-right: 10px;
        color: #ffffff;
        font-size: 22px;
      }
    }

    .imageList {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 100%;
      height: 60px;

      .bottom_div {
        padding: 5px;
        margin-left: 5px;
        margin-right: 5px;
      }

      .bottom_div_choose {
        padding: 4px;
        border: 1px solid yellow;
        margin-left: 5px;
        margin-right: 5px;
      }
    }
  }

  .leftButton {
    position: absolute;
    left: 40px;
    top: 45%;
    z-index: 1000;
    background: #9c9c9c;
    border-radius: 50px;
    width: 50px;
    height: 50px;

    display: flex;
    align-items: center;
    justify-content: center;
  }
  .rightButton {
    position: absolute;
    right: 40px;
    top: 45%;
    z-index: 1000;
    background: #9c9c9c;
    border-radius: 50px;
    width: 50px;
    height: 50px;

    display: flex;
    align-items: center;
    justify-content: center;
  }
  .eyeButton {
    position: absolute;
    right: 40px;
    top: 45px;
    background: #ffffff;
    width: 50px;
    height: 100px;
  }
  .tipChoose {
    position: absolute;
    background: #1c1c1c;
    color: #ffffff;
    padding: 5px;
    top: 35px;
    width: 100px;
  }
</style>
