<template>
  <div class="canvas-container" ref="canvasContainer">
    <div class="canvas float-left" ref="yfcontainer" v-loading="loading">
      <!-- 画布 -->
      <canvas
        :style="{
          width: canvasSize.width + 'px',
          height: canvasSize.height + 'px',
        }"
        canvas-id="yfCanvas"
        id="yfCanvas"
      ></canvas>
      <!-- 文本标签 -->
      <!-- <div class="element-layer">
        <span
          class="label-link cursor"
          v-for="tag in rectangles"
          @click="deleteSpan($event, tag.id)"
          :key="tag.id"
          :style="linkStyle(tag)"
        >
          <span class="delete" @click.stop="deleteSpan($event, tag.id)">✖</span>
        </span>
      </div> -->
    </div>
  </div>
</template>

<script>
import Panel from './comps/panel.vue';
import Tools from './comps/tools.vue';
import Annotation from './comps/Annotation.vue';
let myRatio = 1;
export default {
  props: {
    markItem: {
      type: Object,
      default: () => ({
        addr: 'https://bigdata-image.oss-cn-hangzhou.aliyuncs.com/Basics/cbd/666000000000001/2025/7/11/001.jpg',
        mark: [],
        is_mark: 0,
        label:
          "[{'71': [480, 47, 520, 91, 1.0]}, {'71': [513, 102, 545, 155, 1.0]}, {'71': [690, 238, 740, 272, 1.0]}, {'71': [298, 471, 335, 514, 1.0]}, {'71': [250, 379, 300, 407, 1.0]}, {'71': [106, 40, 143, 89, 1.0]}, {'71': [46, 12, 124, 58, 0.99]}, {'71': [2, 90, 41, 133, 0.98]}, {'71': [767, 189, 799, 237, 0.98]}, {'71': [721, 175, 758, 216, 0.92]}, {'71': [685, 132, 727, 166, 0.35]}]",
      }),
    },
    isInitFullScreen: {
      type: Boolean,
      default: false,
    },
    reIdentify: {
      type: Boolean,
      default: true,
    },
    title: {
      type: String,
      default: '目录',
    },

    typeName: {
      type: Number,
      default: 1, // 1: 测报灯  2：病虫害可视监测 3：吸虫塔 4：孢子仪
    },
  },
  watch: {
    markItem: {
      handler(newVal) {
        console.log('markItem变化:', newVal, this.ctx);
        // 当markItem变化时，重新加载图片和标注
        if (!newVal.addr && this.ctx) {
          this.clearCanvas();
          return;
        }
        if (this.ctx) {
          this.loadImage();
        }
      },
      deep: true,
    },
  },
  components: {
    Panel,
    Tools,
    Annotation,
  },
  name: 'Draw',
  computed: {
    inputStyle() {
      return {
        left: `${this.inputPosition.x}px`,
        top: `${this.inputPosition.y}px`,
      };
    },
    canvasStyle() {
      return {
        cursor: this.mode === 'draw' ? 'crosshair' : 'grab',
      };
    },
    fullScreenHtml() {
      return this.$refs.canvasContainer;
    },
  },
  data() {
    return {
      imgTimer: false, // 图片时间戳
      ctx: null,
      scale: 1, // 画布的缩放
      imageScale: 1, // 图片的原始缩放
      markScale: 1, // 绘制的缩放
      baseScale: 0.31,
      offsetX: 0,
      offsetY: 0,
      mode: 'drag', // 'draw' / 'drag'
      modeLabels: {
        draw: 'D绘制',
        drag: 'S拖拽',
        select: '空格选择',
      },
      isDragging: false,
      isDrawing: false,
      lastX: 0,
      lastY: 0,
      startX: 0,
      startY: 0,
      rectangles: [],
      currentRect: null,
      selectedRect: null,
      backgroundImage: null,
      imageLoaded: false,
      originalImageSize: { width: 0, height: 0 },
      isFullScreen: false,
      imageRect: { x: 0, y: 0, width: 0, height: 0 }, // 存储图片显示区域
      showInput: false,
      currentLabel: '',
      inputPosition: { x: 0, y: 0 },
      currentRectId: null,

      lastImageScale: 1,
      loading: true,
      isMoving: false,
      colorMap: {}, // 用于存储文本和颜色的映射关系
      tempColor: '#FFFF00', // 绘制时黄色半透明
      finalColor: '#FF0000', // 完成后红色半透明
      changeLeftActive: false,
      changeRightActive: false,
      colorIndex: 0,
      originDataLength: 0, // 用于记录原始数据长度
      pestLibrary: {},
      canvasSize: { width: 310, height: 279 },
    };
  },
  created() {
    this.getAllPestList();
  },
  mounted() {
    // console.log('初始化markItem:', this.markItem)

    uni.getSystemInfo({
      success: (res) => {
        this.canvasSize.width = res.windowWidth - (24 * 2 + 16 * 2);
      },
    });
    this.$nextTick(() => {});
  },
  beforeDestroy() {},
  methods: {
    // 切换上一个下一个
    changeItem(type) {
      this.$emit('changeItem', { type: type, isFullScreen: this.isFullScreen });
    },
    changeMode(modeType) {
      this.mode = modeType;
    },

    resetPest() {
      // 通知业务上层处理逻辑
      this.exitFullScreen();
      this.$emit('resetPest');
    },
    // 查看原图
    checkImagePreview() {
      this.$refs.imgPreview.click();
    },

    linkStyle(tag) {
      let x = Math.min(tag.startX, tag.endX);
      let y = Math.min(tag.startY, tag.endY);

      const top = y * this.scale + this.offsetY - 20 + 'px';
      const left = x * this.scale + this.offsetX + 'px';
      return {
        top,
        left,
        color: tag.color,
        'pointer-events': this.isMoving ? 'none' : 'auto',
      };
    },
    initCanvas() {
      this.ctx = uni.createCanvasContext('yfCanvas', this);
      console.log(this.ctx);
      this.loadImage();
    },

    loadImage() {
      if (!this.markItem.addr) {
        this.loading = false;
        return;
      }

      uni.getImageInfo({
        src: this.markItem.addr,
        success: (res) => {
          this.imageLoaded = true;
          this.backgroundImage = res;
          this.originalImageSize = {
            width: this.backgroundImage.width,
            height: this.backgroundImage.height,
          };
          this.rectangles = []; // 清除之前的标注
          this.selectedRect = null;
          this.adjustImagePosition();
          this.initMarkData();
          this.draw();
          this.loading = false;
        },
        fail: (err) => {
          this.loading = false;
          this.$message.error('图片加载失败');
        },
      });
    },

    adjustImagePosition() {
      if (!this.imageLoaded) return;

      const canvas = this.canvasSize;
      const canvasAspect = canvas.width / canvas.height;
      const imageAspect =
        this.originalImageSize.width / this.originalImageSize.height;

      // 计算等比缩放的尺寸
      if (imageAspect > canvasAspect) {
        this.imageScale = canvas.width / this.originalImageSize.width;
      } else {
        this.imageScale = canvas.height / this.originalImageSize.height;
      }
      // this.imageScale = 0.8
      // 根据图片的宽度来定义缩放比例
      if (this.originalImageSize.width >= 5000) {
        this.baseScale = 0.25;
      } else if (this.originalImageSize.width >= 4000) {
        this.baseScale = 0.31;
      } else if (this.originalImageSize.width < 4000) {
        this.baseScale = 0.4;
      }
      // 用来处理图片等比例显示
      this.markScale = 1 - (this.baseScale - this.imageScale) / this.baseScale;
      // 窗口大小改变的时候使用
      myRatio = this.imageScale / this.lastImageScale;

      this.lastImageScale = this.imageScale;
      // 计算图片显示区域
      this.imageRect = {
        x: 0,
        y: 0,
        width: this.originalImageSize.width * this.imageScale,
        height: this.originalImageSize.height * this.imageScale,
      };

      // 初始位置居中
      this.scale = 1;
      this.offsetX = (canvas.width - this.imageRect.width) / 2;
      this.offsetY = (canvas.height - this.imageRect.height) / 2;
    },

    isPointInImage(x, y) {
      return (
        x >= 0 &&
        x <= this.imageRect.width &&
        y >= 0 &&
        y <= this.imageRect.height
      );
    },
    constrainRect(rect) {
      // 确保矩形完全在图片区域内
      const startX = Math.max(0, Math.min(this.imageRect.width, rect.startX));
      const startY = Math.max(0, Math.min(this.imageRect.height, rect.startY));
      const endX = Math.max(0, Math.min(this.imageRect.width, rect.endX));
      const endY = Math.max(0, Math.min(this.imageRect.height, rect.endY));

      return {
        ...rect,
        startX,
        startY,
        endX,
        endY,
      };
    },

    handleLabelChange() {
      this.draw();
    },

    getRectAt(x, y) {
      // 从后往前检查，这样最后绘制的矩形会优先被选中
      for (let i = this.rectangles.length - 1; i >= 0; i--) {
        const rect = this.rectangles[i];
        const left = Math.min(rect.startX, rect.endX);
        const right = Math.max(rect.startX, rect.endX);
        const top = Math.min(rect.startY, rect.endY);
        const bottom = Math.max(rect.startY, rect.endY);

        if (x >= left && x <= right && y >= top && y <= bottom) {
          return rect;
        }
      }
      return null;
    },

    deleteSelected() {
      if (this.selectedRect) {
        this.deleteRect(this.selectedRect.id);
        this.selectedRect = null;
      }
    },

    deleteRect(id) {
      this.rectangles = this.rectangles.filter((rect) => rect.id !== id);
      if (this.selectedRect && this.selectedRect.id === id) {
        this.selectedRect = null;
      }
      this.showInput = false;
      this.currentRectId = null;
      this.draw();
    },
    deleteSpan(e, id) {
      e.preventDefault();
      e.stopPropagation();
      this.isDrawing = false;
      this.deleteRect(id);
    },
    clearCanvas() {
      this.loading = false;
      this.imageLoaded = false;
      this.rectangles = [];
      this.selectedRect = null;
      this.showInput = false;
      this.currentRectId = null;
      const canvas = this.canvasSize;
      const ctx = this.ctx;

      // 清除画布
      ctx.clearRect(0, 0, canvas.width, canvas.height);
    },
    // 修改后的 draw 方法
    draw() {
      const canvas = this.canvasSize;
      const ctx = this.ctx;

      // 清除画布
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      console.log(this.offsetX, this.offsetY);
      // 保存当前状态
      ctx.save();

      // 应用变换（缩放和平移）
      ctx.translate(this.offsetX, this.offsetY);
      ctx.scale(this.scale, this.scale);

      // 绘制背景图片（不再除以this.scale）
      if (this.imageLoaded && this.backgroundImage) {
        const displayWidth = this.originalImageSize.width * this.imageScale;
        const displayHeight = this.originalImageSize.height * this.imageScale;
        // ctx.imageSmoothingEnabled = true
        // ctx.imageSmoothingQuality = 'high'
        ctx.drawImage(
          this.backgroundImage.path,
          0,
          0,
          displayWidth,
          displayHeight
        );
      }
      console.log('绘制：：', this.rectangles);
      // 绘制所有已保存的矩形（添加约束）
      this.rectangles.forEach((rect) => {
        const constrainedRect = this.constrainRect(rect);
        this.drawRectangle(constrainedRect, rect === this.selectedRect);
      });

      // 绘制当前正在绘制的矩形（添加约束）
      if (this.currentRect) {
        const constrainedRect = this.constrainRect(this.currentRect);
        this.drawRectangle(constrainedRect, false);
      }

      // 恢复状态
      ctx.restore();
      ctx.draw();
    },

    drawRectangle(rect, isSelected) {
      const ctx = this.ctx;

      const x = Math.min(rect.startX, rect.endX);
      const y = Math.min(rect.startY, rect.endY);
      const width = Math.abs(rect.endX - rect.startX);
      const height = Math.abs(rect.endY - rect.startY);

      // 绘制矩形填充

      ctx.strokeStyle = rect.color;
      ctx.lineWidth = 2 / this.scale;
      ctx.strokeRect(x, y, width, height);
      // 绘制标签文本
      if (rect.text) {
        ctx.fillStyle = rect.color;
        ctx.font = `${14 / this.scale}px Arial`;
        ctx.fillText(rect.text, x + 12 / this.scale, y - 6 / this.scale);
      }
    },

    // 获取数据
    getData() {
      const data = this.rectangles.map((rect) => {
        return {
          startX: parseFloat((rect.startX / this.markScale).toFixed(2)),
          startY: parseFloat((rect.startY / this.markScale).toFixed(2)),
          width: parseFloat(
            (Math.abs(rect.startX - rect.endX) / this.markScale).toFixed(2)
          ),
          height: parseFloat(
            (Math.abs(rect.startY - rect.endY) / this.markScale).toFixed(2)
          ),
          text: rect.text,
        };
      });
      this.originDataLength = data.length;
      return data;
      // return JSON.stringify(data)
    },
    // 处理渲染数据
    async initMarkData() {
      const colorList = [
        '#FF0000',
        '#00FFC2',
        '#FF00A8',
        '#120080',
        '#BDFF00',
        '#FFB800',
        '#5E8000',
        '#FF5C00',
        '#00FF75',
        '#00F0FF',
        '#0094FF',
        '#FFFFFF',
        '#007880',
        '#00C2FF',
        '#C74C4C',
        '#EB00FF',
      ];
      if (this.markItem.is_mark === 0) {
        // 机器标注，取label
        let aiLabel = [];
        if (this.markItem.label) {
          aiLabel = JSON.parse(this.markItem.label.replace(/'/g, '"'));
        }
        this.rectangles = [];
        console.log('00000', aiLabel);
        aiLabel.forEach((item, index) => {
          for (let key in item) {
            const [startX, startY, endX, endY] = item[key];
            const text = this.pestLibrary[key];
            if (!this.colorMap[text]) {
              this.colorMap[text] =
                colorList[this.colorIndex % colorList.length];
              this.colorIndex += 1;
              if (this.colorIndex >= colorList.length) {
                this.colorIndex = 0;
              }
            }
            this.rectangles.push({
              id: Date.now() + index,
              text: text,
              startX: startX * this.imageScale,
              startY: startY * this.imageScale,
              endX: endX * this.imageScale,
              endY: endY * this.imageScale,
              color: this.colorMap[text],
              imageScale: this.imageScale,
            });
          }
        });
        this.originDataLength = this.rectangles.length;
      } else {
        // 人工标注，取mark
        console.log('this.colorIndex', this.colorIndex);
        this.rectangles = [];
        this.markItem.mark.map((item, index) => {
          const { startX, startY, width, height, text } = item;
          if (!this.colorMap[text]) {
            this.colorMap[text] = colorList[this.colorIndex % colorList.length];
            this.colorIndex += 1;
            if (this.colorIndex >= colorList.length) {
              this.colorIndex = 0;
            }
          }
          this.rectangles.push({
            id: Date.now() + index,
            text: text,
            startX: Number(startX) * this.markScale,
            startY: Number(startY) * this.markScale,
            endX:
              Number(startX) * this.markScale + Number(width) * this.markScale,
            endY:
              Number(startY) * this.markScale + Number(height) * this.markScale,
            color: this.colorMap[text],
            imageScale: this.imageScale,
          });
        });
        this.originDataLength = this.rectangles.length;
      }
      console.log('原始rectangles', this.rectangles);
    },
    // 保存标注
    saveLabel() {
      this.$emit('saveLabel', this.getData());
    },
    async getAllPestList() {
      const res = await this.$myRequest({
        url: '/api/api_gateway?method=forecast.pest_info.pest_dict',
        data: {
          type_name: this.typeName,
        },
      });
      // console.log('获取到的病虫害数据', res)
      this.pestLibrary = res;
      this.initCanvas();
    },
  },
};
</script>

<style lang="less" scoped>
@primary-color: #018b3f !important;
::v-deep .el-button--primary {
  background-color: @primary-color !important;
}
.canvas-container {
  width: 100%;
  height: 100%;
  position: relative;
  background: #ffffff;
  padding-top: 10px;
  .virtual-canvas {
    /* 2025安全隐藏方案 */
    position: absolute !important;
    clip: rect(0 0 0 0) !important;
    pointer-events: none !important;
    opacity: 0 !important;
    z-index: -9999 !important;
  }
  .canvas {
    width: 100%;
    height: 100%;
    overflow: hidden;
    background-color: #ffffff;
    border: 1px solid #e4e7ed;
    box-sizing: border-box;
    position: relative;
  }
  .canvas-timer {
    position: absolute;
    left: 16px;
    top: 16px;
    z-index: 2;
    color: #ffffff;
    font-size: 23px;
  }
  .panel {
    width: 30%;
    height: calc(100% - 60px);
    background: #ffffff;
    padding-left: 10px;
    box-sizing: border-box;
    position: relative;
    z-index: 3;
    .save {
      height: 60px;
      button {
        margin: 14px;
      }
    }
  }
  .controls {
    // padding: 3px 15px;
    width: 70%;
    height: 64px;
    box-sizing: border-box;
    position: relative;
    z-index: 3;
    // background: rgba(0, 0, 0, 0.3);
  }
  .img-timer {
    position: absolute;
    left: 0;
    top: 22px;
  }
  .info {
    // width: 100%;
    // color: #ffffff;
    // overflow: hidden;
    // text-align: center;
    .tools {
      // width: 365px;
      height: 64px;
      // padding: 0 10%;
      display: flex;
      align-items: center;
      justify-content: center;
      // background: rgba(0, 0, 0, 0.6);
      border-radius: 4px;
      gap: 10px;
      // margin: 0 auto;
      color: rgba(0, 0, 0, 0.6);
      .active {
        background: @primary-color;
        color: #ffffff;
      }
      .split {
        color: #b9b9b9;
        margin: 0 5px;
        font-size: 14px;
      }
    }
    .float-right {
      width: 30%;
    }
    .img-preview {
      display: none;
      width: 20px;
      position: absolute;
    }
  }

  .info span {
    white-space: nowrap;
    .active {
      color: @primary-color;
      margin-right: 5px;
    }
  }

  .info button {
    font-size: 26px;
    padding: 2px 4px;
    background: none;
    border: none;
    border-radius: 3px;
    cursor: pointer;
    white-space: nowrap;
    color: #434343;
  }

  .info button:disabled {
    cursor: not-allowed;
  }
  .element-layer {
    .label-link {
      position: absolute;
      z-index: 2;
      user-select: none;
      pointer-events: auto;
    }
  }
}
</style>
