<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;
/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>
