<template>
  <div class="mark-handle">
    <div v-if="isBookShelf && currentMarkData && currentMarkData.shelfId !== undefined" class="mark-img">
      <canvas :id="'canvas' + currentMarkData.shelfId" :width="width" :height="height" />
    </div>
    <div v-else-if="!isBookShelf && currentMarkData && currentMarkData.id !== undefined" class="mark-img">
      <canvas :id="'canvas' + currentMarkData.id" :width="width" :height="height" />
    </div>
    <div class="mark-right">
      <ul v-if="!isBookShelf" class="mark-info">
        <li>
          <p>所属机构</p>
          <span>{{ user.fonds.fondsName }}</span>
        </li>
        <li>
          <p>所属楼层</p>
          <span>{{ currentMarkData && currentMarkData.floorName }}</span>
        </li>
        <li>
          <p>书架</p>
          <span>{{ currentMarkData && currentMarkData.booksheflCount }}</span>
        </li>
        <li><span :class="['row-state', currentMarkData && currentMarkData.signPoint ? 'end-state' : 'cancel-state' ]">{{ currentMarkData && currentMarkData.signPoint ? '已标注': '未标注' }}</span></li>
      </ul>
      <ul v-else class="mark-info">
        <li>
          <p>所属机构</p>
          <span>{{ user.fonds.fondsName }}</span>
        </li>
        <li>
          <p>所属楼层</p>
          <span>{{ currentMarkData && currentMarkData.floorName }}</span>
        </li>
        <li>
          <p>所属区域</p>
          <span>{{ currentMarkData && currentMarkData.regionName }}</span>
        </li>
        <li>
          <p>单/双面</p>
          <span>{{ currentMarkData && currentMarkData.rowType === 1 ? '单面' :'双面' }}</span>
        </li>
        <li>
          <p>书架规格</p>
          <span>{{ currentMarkData && currentMarkData.shelfFloor+ ' X ' + currentMarkData.shelfShelf }}</span>
        </li>
        <li><span :class="['row-state', true ? 'end-state' : 'cancel-state' ]">{{ true ? '已标注': '未标注' }}</span></li>
      </ul>
      <div class="mark-button">
        <el-button type="primary" :disabled="!isDrawing" @click="clean"><i class="iconfont icon-shanchu" />清空</el-button>
        <el-button type="primary" :disabled="isDrawing" @click="drawPolygon"><i class="el-icon-edit" style="font-weight: bold; padding-right: 4px; font-size: 16px;" />标注</el-button>
        <el-button type="primary" :disabled="!isDrawing" @click="submitDraw"><i class="el-icon-folder-checked" style="font-weight: bold; padding-right: 4px; font-size: 16px;" />保存</el-button>
      </div>
    </div>
    <img id="expImg" :src="imageUrl">
  </div>
</template>

<script>
import { saveLibraryRegionSignPoint } from '@/api/area/index'
import { saveBookShelfSignPoint } from '@/api/shelf/index'
import { fabric } from 'fabric'
import { mapGetters } from 'vuex'
export default {
  name: 'Mark',
  props: {
    currentMarkData: {
      type: Object,
      require: true,
      default: function() {
        return {}
      }
    },
    imageUrl: {
      type: String,
      default: ''
    },
    isBookShelf: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      bgImgFlag: true,
      bgImgSrc: this.imageUrl,
      width: 900,
      height: 600,
      canvas: {},
      mouseFrom: {},
      mouseTo: {},
      drawWidth: 2, // 笔触宽度
      drawingObject: null, // 当前绘制对象
      moveCount: 1, // 绘制移动计数器
      doDrawing: false, // 绘制状态
      // polygon 相关参数
      polygonMode: false,
      pointArray: [],
      lineArray: [],
      savePointsGroup: [],
      activeShape: false,
      activeLine: '',
      line: {},
      deleteIconURL: require('@/assets/images/closed.png'),
      drawinfo: null,
      isDrawing: false
    }
  },
  computed: {
    ...mapGetters([
      'user',
      'baseApi'
    ])
  },
  watch: {
    width() {
      this.canvas.setWidth(this.width)
    },
    height() {
      this.canvas.setHeight(this.height)
    },
    currentMarkData: {
      handler(newVal, oldVal) {
        // 检查 newVal 是否为 null 或 undefined
        if (!newVal) {
          console.log('newVal is null or undefined')
          return
        }

        // 提取公共逻辑
        const handleIdChange = (newId, oldId, idKey) => {
          if (newId !== oldId) {
            console.log('id has changed')
            console.log('handler')
            this.canvas.clear()
            this.canvas.dispose()
            this.drawinfo = newVal.signPoint ? JSON.parse(newVal.signPoint) : null
            this.$nextTick(() => {
              this.$refs.markRefs.initCanvas()
            })
          }
        }

        if (this.isBookShelf && oldVal && oldVal.shelfId !== undefined) {
          handleIdChange(newVal.shelfId, oldVal.shelfId, 'shelfId')
        } else if (!this.isBookShelf && oldVal && oldVal.id !== undefined) {
          handleIdChange(newVal.id, oldVal.id, 'id')
        }
      },
      deep: true
    },

    imageUrl(newVal, oldVal) {
      if (newVal !== oldVal) {
        console.log('imageUrl')
      }
    }
  },
  mounted() {
    // this.$nextTick(() => {
    //   console.log('mounted')
    //   this.drawinfo = this.currentMarkData && this.currentMarkData.signPoint ? JSON.parse(this.currentMarkData.signPoint) : null
    //   this.initCanvas()
    // })
  },
  beforeDestroy() {
    if (this.canvas) {
      this.canvas.clear()
      this.canvas.dispose()
    }
  },
  methods: {
    initCanvas() {
      // 检查 currentMarkData 是否存在
      if (!this.currentMarkData) {
        console.error('currentMarkData is null or undefined')
        return
      }

      const canvasId = `canvas${this.isBookShelf ? this.currentMarkData.shelfId : this.currentMarkData.id}`

      // 初始化 fabric.js 画布
      this.canvas = new fabric.Canvas(canvasId, {
        skipTargetFind: false,
        selectable: false,
        selection: false
      })
      this.canvas.selectionColor = 'rgba(0,0,0,0.05)'
      this.canvas.on('mouse:down', this.mousedown)
      this.canvas.on('mouse:move', this.mousemove)
      this.canvas.on('object:moving', this.objectMoving)
      console.log('this.drawinfo', this.drawinfo)
      console.log('this.canvas', this.canvas)
      if (this.drawinfo) {
        console.log('444')
        this.loadDraw()
      } else {
        console.log('555')
        this.isDrawing = false
        this.bgImgFlag = true
        const imgElement = document.getElementById('expImg')
        imgElement.src = this.imageUrl
        this.loadExpImg()
      }
    },
    // 从已渲染的DOM元素加载图片至canvas
    loadExpImg() {
      console.log('loadExpImg')
      const imgElement = document.getElementById('expImg')
      const newWidth = this.canvas.width
      console.log('newWidth', newWidth)
      imgElement.onload = () => {
        // console.log('imgElement.src', imgElement.src)
        const newHeight = newWidth / (imgElement.width / imgElement.height)
        new fabric.Image.fromURL(
          imgElement.src,
          (img) => {
            img.set(
              {
                originX: 'center',
                originY: 'center',
                scaleX: newWidth / imgElement.width,
                scaleY: newHeight / imgElement.height
              },
              { crossOrigin: 'anonymous' }
            )
            img.on('scaling', (e) => {
              // 拉伸事件
              const h = img.scaleY
              const w = img.scaleX
              if (h !== w || w === h) {
                // 判断缩放值相等或不相等后执行图片等比缩放
                if (e.e.movementY === -1 || e.e.movementY === 1) {
                  img.scale(h) // 缩放
                } else {
                  img.scale(w)
                }
              }
            })
            img.setCoords()
            img.centeredScaling = true
            img.centerTransform = true
            this.canvas.add(img)
            this.canvas.centerObject(img)
            this.canvas.renderAll()
          },
          {
            selectable: true,
            hasControls: true,
            lockRotation: true, // 禁止旋转
            centeredScaling: true,
            zIndex: -99,
            isBgImg: true
          }
        )
      }
    },
    // 对象移动时的事件处理
    objectMoving(e) {
      const target = e.target
      if (target.type === 'polygon') {
        target.setCoords()
        // 更新params.pointInfo以确保点信息是最新的
        // const points = target.points.map(p => ({
        //   x: p.x + target.left,
        //   y: p.y + target.top
        // }));
        // const index = params.pointInfo.findIndex(info => info.pointInfo[0].x === target.points[0].x && info.pointInfo[0].y === target.points[0].y);
        // if (index !== -1) {
        //   params.pointInfo[index] = { pointInfo: points };
        // } else {
        //   params.pointInfo.push({ pointInfo: points });
        // }
      }
    },
    submitDraw() {
      const saveCanvasData = {
        pointInfo: [],
        imgInfo: ''
        // img: ''
      }
      this.canvas
        .toJSON(['isBgImg'])
        .objects.forEach((item) => {
          const element = {
            pointInfo: ''
          }
          if (item?.points) {
            element.pointInfo = item.points
            saveCanvasData.pointInfo.push(element)
          }
          if (item.isBgImg) {
            saveCanvasData.imgInfo = item
            // params.img = item.src
            delete saveCanvasData.imgInfo.src
          }
        })
      console.log('saveCanvasData', saveCanvasData)

      if (this.isBookShelf) {
        const params = {
          'id': this.currentMarkData.shelfId,
          'signPoint': JSON.stringify(saveCanvasData)
        }
        saveBookShelfSignPoint(params).then(res => {
          console.log(res)
          if (res) {
            this.$message({ message: '当前书架标注成功', type: 'success', offset: 8 })
            this.$emit('handleCloseDialog')
          }
        }).catch(err => {
          console.log(err)
        })
      } else {
        const params = {
          'id': this.currentMarkData.id,
          'signPoint': JSON.stringify(saveCanvasData)
        }
        saveLibraryRegionSignPoint(params).then(res => {
          if (res) {
            this.$message({ message: '当前区域标注成功', type: 'success', offset: 8 })
            this.$emit('handleCloseDialog')
          }
        }).catch(err => {
          console.log(err)
        })
      }
    },
    // 鼠标按下时触发
    mousedown(e) {
      if (e === undefined) return
      // 记录鼠标按下时的坐标
      const xy =
				e.pointer || this.transformMouse(e.e.offsetX, e.e.offsetY)
      this.mouseFrom.x = xy.x
      this.mouseFrom.y = xy.y
      this.doDrawing = true

      this.canvas.skipTargetFind = false
      try {
        console.log('this.pointArray', this.pointArray)
        // 判断是否闭合多边形，点击红点时闭合多边形
        if (this.pointArray.length > 1) {
          // e.target.id == this.pointArray[0].id 表示点击了初始红点
          if (e.target && e.target.id === this.pointArray[0].id) {
            this.generatePolygon()
            console.log('画完')
            this.isDrawing = true
            return
          } else {
            console.log('未画完')
            this.isDrawing = false
          }
        }
        // 未点击红点即闭合点则继续作画
        if (this.polygonMode) {
          console.log('作画')
          this.addPoint(e)
        }
      } catch (error) {
        console.log(error)
      }
    },
    // 鼠标松开执行
    mouseup(e) {
      if (e === undefined) return
      const xy =
				e.pointer || this.transformMouse(e.e.offsetX, e.e.offsetY)
      this.mouseTo.x = xy.x
      this.mouseTo.y = xy.y
      this.drawingObject = null
      this.moveCount = 1

      // 如果当前操作的是多边形，更新坐标
      if (this.activeShape && this.activeShape.type === 'polygon') {
        this.activeShape.setCoords()
      }
    },
    // 鼠标滚轮放大缩小
    mouse(e) {
      if (undefined === e) return
      let zoom = (e.e.deltaY > 0 ? -0.1 : 0.1) + this.canvas.getZoom()
      zoom = Math.max(0.8, zoom)
      // 最小为原来的1/10
      zoom = Math.min(3, zoom)
      // 最大是原来的3倍
      const zoomPoint = new fabric.Point(e.e.pageX, e.e.pageY)
      this.canvas.zoomToPoint(zoomPoint, zoom)
    },
    // 鼠标移动过程中已经完成了绘制
    mousemove(e) {
      if (e === undefined) return
      if (this.moveCount % 2 === 0 && !this.doDrawing) {
        // 减少绘制频率
        return
      }
      this.moveCount++
      const xy =
				e.pointer || this.transformMouse(e.e.offsetX, e.e.offsetY)
      this.mouseTo.x = xy.x
      this.mouseTo.y = xy.y
      if (this.activeLine && this.activeLine.class === 'line') {
        const pointer = this.canvas.getPointer(e.e)
        this.activeLine.set({
          x2: pointer.x,
          y2: pointer.y
        })
        const points = this.activeShape.get('points')
        points.push({
          x: pointer.x,
          y: pointer.y,
          zIndex: 1
        })
        this.activeShape.set({
          points: points
        })
        this.canvas.renderAll()
      }
    },
    // 从画布中删除当前选中的对象
    deleteObj() {
      const activeObjects = this.canvas.getActiveObjects()
      if (activeObjects.length > 0) {
        activeObjects.forEach((item) => {
          this.canvas.remove(item)
        })
        this.canvas.renderAll()
      }
    },
    // 转换鼠标坐标
    transformMouse(mouseX, mouseY) {
      return {
        x: mouseX,
        y: mouseY
      }
    },
    // 绘制多边形开始
    drawPolygon() {
      console.log(1111)
      if (this.bgImgFlag) {
        this.canvas.getObjects().forEach((obj) => {
          if (obj.isBgImg) {
            obj.hasControls = false
            obj.selectable = false
            obj.evented = false
          }
        })
        this.bgImgFlag = false
        this.canvas.renderAll()
      }
      this.polygonMode = true
      this.pointArray = [] // 顶点集合
      this.lineArray = [] // 线集合
      this.canvas.isDrawingMode = false
    },
    addPoint(e) {
      const random = Math.floor(Math.random() * 10000)
      const id = new Date().getTime() + random
      const circle = new fabric.Circle({
        radius: 5,
        fill: '#ffffff',
        stroke: '#333333',
        strokeWidth: 0.5,
        left: (e.pointer?.x || e.e.layerX) / this.canvas.getZoom(),
        top: (e.pointer?.y || e.e.layerY) / this.canvas.getZoom(),
        selectable: false,
        hasBorders: false,
        hasControls: false,
        originX: 'center',
        originY: 'center',
        id,
        objectCaching: false
      })
      if (this.pointArray.length === 0) {
        circle.set({ fill: 'rgba(196,43, 1, 1)' })
      }
      const points = [
        (e.pointer?.x || e.e.layerX) / this.canvas.getZoom(),
        (e.pointer?.y || e.e.layerY) / this.canvas.getZoom(),
        (e.pointer?.x || e.e.layerX) / this.canvas.getZoom(),
        (e.pointer?.y || e.e.layerY) / this.canvas.getZoom()
      ]
      const line = new fabric.Line(points, {
        strokeWidth: 2,
        fill: 'rgba(196,43, 1, 1)',
        stroke: 'rgba(196,43, 1, 1)',
        class: 'line',
        originX: 'center',
        originY: 'center',
        selectable: false,
        hasBorders: false,
        hasControls: false,
        evented: false,
        objectCaching: false
      })
      if (this.activeShape) {
        const pos = this.canvas.getPointer(e.e)
        const points = this.activeShape.get('points')
        points.push({ x: pos.x, y: pos.y })
        const polygon = new fabric.Polygon(points, {
          stroke: '#333333',
          strokeWidth: 1,
          fill: 'rgba(196,43, 1, 0.3)',
          opacity: 0.3,
          selectable: false,
          hasBorders: false,
          hasControls: false,
          evented: false,
          objectCaching: false
        })
        this.canvas.remove(this.activeShape)
        this.canvas.add(polygon)
        this.activeShape = polygon
        this.canvas.renderAll()
      } else {
        const polyPoint = [
          {
            x: (e.pointer?.x || e.e.layerX) / this.canvas.getZoom(),
            y: (e.pointer?.y || e.e.layerY) / this.canvas.getZoom()
          }
        ]
        const polygon = new fabric.Polygon(polyPoint, {
          stroke: '#333333',
          strokeWidth: 1,
          fill: '#cccccc',
          opacity: 0.3,
          selectable: false,
          hasBorders: false,
          hasControls: false,
          evented: false,
          objectCaching: false
        })
        this.activeShape = polygon
        this.canvas.add(polygon)
      }
      this.activeLine = line
      this.pointArray.push(circle)
      this.lineArray.push(line)
      this.canvas.add(line)
      this.canvas.add(circle)
    },
    generatePolygon() {
      const points = []
      this.pointArray.forEach((point) => {
        points.push({ x: point.left, y: point.top })
        this.canvas.remove(point)
      })
      this.lineArray.forEach((line) => {
        this.canvas.remove(line)
      })
      if (this.activeShape) {
        this.canvas.remove(this.activeShape)
      }
      if (this.activeLine) {
        this.canvas.remove(this.activeLine)
      }

      const polygon = new fabric.Polygon(points, {
        stroke: 'rgba(196,43, 1, 1)',
        strokeWidth: this.drawWidth,
        fill: 'rgba(196,43, 1, 0.3)',
        opacity: 1,
        selectable: false,
        hasBorders: false,
        hasControls: false,
        name: '测试架号name1'
      })

      let maxIndex = 0
      this.canvas._objects.forEach((obj) => {
        if (obj.index > maxIndex) maxIndex = obj.index
      })
      polygon.index = maxIndex + 1
      this.canvas.add(polygon)

      this.activeLine = null
      this.activeShape = null
      this.polygonMode = false
      this.doDrawing = false
      fabric.Image.fromURL(this.deleteIconURL, this.deletecallback)
    },
    // 从画布中删除当前选中的对象
    deleteObject() {
      const activeObject = this.canvas.getActiveObject()
      if (activeObject) {
        this.canvas._objects.forEach(item => {
          if (item.index === activeObject.index) {
            this.canvas.remove(item)
          }
        })

        const onlyBgImgItems = this.canvas._objects.filter(item => item.isBgImg)
        const allItemsAreBgImg = this.canvas._objects.length / 2 === onlyBgImgItems.length
        console.log('allItemsAreBgImg', allItemsAreBgImg)

        if (allItemsAreBgImg) {
          this.canvas.clear()
          this.bgImgFlag = true
          const imgElement = document.getElementById('expImg')
          imgElement.src = this.imageUrl
          this.isDrawing = false
          this.bgImgFlag = true
          this.loadExpImg()
        }

        this.canvas.remove(activeObject)
        this.canvas.renderAll()
      } else {
        console.log('this.canvas._objects.length', this.canvas._objects.length)
      }
    },
    // 渲染删除按钮
    async deletecallback(img) {
      const self = this
      let max = 0
      for (let i = 1; i < this.canvas._objects.length; i++) {
        if (this.canvas._objects[i].index > max) max = this.canvas._objects[i].index
      }
      img.index = max
      const oImg = await img.set({
        name: 'delete-btn',
        left: this.pointArray[0].left - 20,
        top: this.pointArray[0].top - 20,
        width: 40,
        height: 40,
        angle: 0
      }).scale(0.8)
      this.canvas.add(oImg).renderAll()
      this.canvas.setActiveObject(oImg)
      oImg.on('mousedown', function() {
        self.deleteObject()
      })
    },
    // 回显详情信息
    loadDraw() {
      const self = this
      if (this.currentMarkData.id === '') return
      const pointGroup = self.drawinfo.pointInfo
      const imgInfo = self.drawinfo.imgInfo
      imgInfo.src = self.imageUrl
      this.isDrawing = true

      // 加载底图
      fabric.util.enlivenObjects([imgInfo], objects => {
        objects.forEach(o => {
          o.selectable = false
          o.hasControls = false
          o.centeredScaling = false
          this.canvas.add(o)
        })
        // 处理多边形绘制回显操作
        pointGroup.forEach(async(item, index) => {
          if (item.pointInfo !== '') {
            const polygon = new fabric.Polygon(item.pointInfo, {
              name: item.name,
              stroke: 'rgba(196,43, 1, 1)',
              strokeWidth: self.drawWidth,
              fill: 'rgba(196,43, 1, 0.3)',
              opacity: 1,
              selectable: false,
              hasBorders: false,
              hasControls: false,
              originX: 'left', // 设置原点为左上角
              originY: 'top' // 设置原点为左上角
            })
            polygon.index = index

            self.canvas.add(polygon)
            self.activeLine = null
            self.activeShape = null
            self.polygonMode = false
            self.doDrawing = false

            polygon.on('mousedown', function(e) {
              console.log('Rect222' + (index + 1) + ' clicked', e)
              console.log('e.target.name222', e.target.name)
            })

            polygon.on('mouseover', function(e) {
              console.log('e22', e)
              console.log('e.target22', e.target)
              console.log('e.target.name22', e.target.name)
              // var delta = new fabric.Point(e.e.movementX, e.e.movementY)
              // if(e.target&&e.target.name){
              //   // that.showDialog(e.target.name)
              // }
              this.set({ opacity: 0.3, hoverCursor: 'pointer' })
              this.canvas.renderAll()
            })

            // 监听鼠标移出事件
            polygon.on('mouseout', function() {
              this.set({ opacity: 1 })
              this.canvas.renderAll()
            })

            fabric.Image.fromURL(self.deleteIconURL, async img => {
              const _self = this
              img.index = index
              const oImg = await img.set({
                name: 'delete-btn',
                left: item.pointInfo[0].x - 20,
                top: item.pointInfo[0].y - 20,
                width: 40,
                height: 40,
                angle: 0
              }).scale(0.8)
              this.canvas.add(oImg)
              oImg.on('mousedown', function() {
                _self.deleteObject()
              })
            })
          }
        })
      })
      this.canvas.renderAll()
    },
    // 清除画布
    clean() {
      this.$confirm('确认清空标注吗？', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.canvas.clear()
        this.isDrawing = false
        this.bgImgFlag = true
        const imgElement = document.getElementById('expImg')
        imgElement.src = this.imageUrl
        this.loadExpImg()
      }).catch(() => {
        console.log('取消清空标注')
      })
    }
  }
}
</script>

<style lang="scss" scoped>
#expImg{
  display: none;
}
</style>
