import Base from '../annotation/base';
import { getActualPoint, getClickPoint, createSvg, createElement } from '../annotation/utils';
import { onClickOutsideUp } from '../ui_utils'

export default class RadioButton extends Base {
  constructor ({
    container,
    annotation,
    page,
    viewport,
    scale,
    eventBus,
    layer,
    show = false,
    highlight,
    messageHandler
  }) {
    super({
      container,
      annotation,
      page,
      layer,
      viewport,
      scale,
      eventBus,
    })
    this.messageHandler = messageHandler
    this.hidden = true
    this.initial = false

    this.start = null
    this.end = null

    this.newStart = null
    this.newEnd = null

    this.startCircle = null
    this.endCircle = null

    this.show = show
    this.highlight = highlight

    this.onMousedown = this.handleMouseDown.bind(this)
    this.onMouseup = this.handleMouseUp.bind(this)
    this.onMousemove = this.handleMouseMove.bind(this)
    this.onDelete = this.handleDelete.bind(this)

    this.handlePropertyPanel = this.handlePropertyPanel.bind(this)
    this.setProperty = this.setProperty.bind(this)
    this.setHighlight = this.setHighlight.bind(this)
    this.render()
  }

  async render () {
    this.eventBus._on('setProperty', this.setProperty)
    this.eventBus._on('setHighlightForm', this.setHighlight)

    const annotation = this.annotation

    if (!this.annotation.fieldName) {
      this.annotation.fieldName = 'Group_' + this.annotation.date.toLocaleString()
    }

    const { start, end } = this.getActualRect(
      this.viewport,
      this.scale
    )
    this.start = start
    this.end = end

    const rect = this.calculate(start, end)
    
    const annotationContainer = document.createElement('div')
    annotationContainer.id = annotation.name
    annotationContainer.className = 'annotation'
    annotationContainer.style.top = rect.top + 'px'
    annotationContainer.style.left = rect.left + 'px'
    annotationContainer.style.width = rect.width + 'px'
    annotationContainer.style.height = rect.height + 'px'
    annotationContainer.style.backgroundColor = this.highlight ? '#4982E54D' : ''
    annotationContainer.style.overflow = 'hidden'
    this.annotationContainer = annotationContainer
    this.annotationContainer.addEventListener('mousedown', this.handleClick.bind(this))

    let shapeElement
    shapeElement = createElement(
      'div',
      {
        left: 0,
        top: 0,
        width: `${Math.abs(rect.width)}px`,
        height: `${Math.abs(rect.height)}px`,
        position: 'relative'
      }
    )
    this.shapeElement = shapeElement

    this.getImage()
    this.annotationContainer.append(this.shapeElement)
    this.container.append(this.annotationContainer)
    
    let borderElement
    borderElement = createElement(
      'div',
      {
        position: 'absolute',
        left: 0,
        top: 0,
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center',
        width: '100%',
        height: '100%',
        borderColor: annotation.borderColor,
        borderWidth: annotation.borderWidth | 1 + 'px',
        borderStyle: annotation.borderStyle,
        borderRadius: '100%',
        backgroundColor: annotation.backgroundColor,
        opacity: 0
      }
    )
    this.borderElement = borderElement

    // creat shape svg
    const svgElement = createSvg(
      "svg",
      {
        width: "15",
        height: "12",
        viewBox: "0 0 15 12",
        fill: "none"
      },
      {
        width: `${rect.width / 2}px`,
        height: `${rect.height / 2}px`
      }
    )
    this.svgElement = svgElement

    // 填充的图形
    let checkPath = createSvg(
      "path",
      {
        d: 'M14.0908 1.59619 L5.59625 10.0908 L1.00006 5.49457',
        stroke: '#43474D',
        'stroke-width': '2'
      }
    );
    this.checkPath = checkPath

    let circlePath = createSvg(
      "path",
      {
        d: 'M0 7C0 3.13401 3.13401 0 7 0C10.866 0 14 3.13401 14 7C14 10.866 10.866 14 7 14C3.13401 14 0 10.866 0 7Z',
        fill: '#43474D'
      }
    );
    this.circlePath = circlePath

    let crossPath = createSvg(
      "path",
      {
        d: 'M6.00001 7.41421L10.1924 11.6066L11.6066 10.1924L7.41422 6L11.6066 1.80762L10.1924 0.393403L6.00001 4.58579L1.70711 0.292895L0.292897 1.70711L4.58579 6L0.292897 10.2929L1.70711 11.7071L6.00001 7.41421Z',
        fill: '#43474D',
        'fill-rule': 'evenodd',
        'clip-rule': 'evenodd'
      }
    );
    this.crossPath = crossPath

    let diamondPath = createSvg(
      "path",
      {
        d: 'M0 7.07108L7.07107 8.99256e-06L14.1421 7.07108L7.07107 14.1421L0 7.07108Z',
        fill: '#43474D'
      }
    );
    this.diamondPath = diamondPath

    let squarePath = createSvg(
      "rect",
      {
        width: '12',
        height: '12',
        fill: '#43474D'
      }
    );
    this.squarePath = squarePath

    let starPath = createSvg(
      "path",
      {
        d: 'M8 0L10.3794 4.7251L15.6085 5.52786L11.8499 9.2509L12.7023 14.4721L8 12.048L3.29772 14.4721L4.15012 9.2509L0.391548 5.52786L5.62065 4.7251L8 0Z',
        fill: '#43474D'
      }
    );
    this.starPath = starPath

    this.setSelectedShape(annotation.checkStyle)
    if (annotation.isChecked == 0) {
      this.svgElement.style.display = 'none'
    }

    this.borderElement.append(this.svgElement)
    this.shapeElement.append(this.borderElement)

    this.outerLineContainer = document.createElement('div')
    this.outerLineContainer.className = 'outline-container'
    this.deletetButton = createSvg(
      "svg",
      {
        width: "30",
        height: "30",
        viewBox: "0 0 30 30",
        fill: "none",
        class: 'delete-button'
      },
      {
        width: '30px',
        height: '30px'
      }
    );
    this.deletetButton.addEventListener('click', this.onDelete)
    this.deletetButton.innerHTML = this.deleteSvgStr

    const left = (rect.left + rect.width - 30) + 'px'
    const top = (rect.top + rect.height + 8) + 'px'
    this.deletetButton.style.left = left
    this.deletetButton.style.top = top
    
    const outerLine = document.createElementNS("http://www.w3.org/2000/svg", "svg");

    outerLine.style.position = 'absolute'
    outerLine.style.zIndex = 1
    outerLine.style.left = `${rect.left - 4}px`
    outerLine.style.top = `${rect.top - 4}px`
    outerLine.style.width = `${rect.width + 4 * 2}px`
    outerLine.style.height = `${rect.height + 4 * 2}px`
    this.outerLine = outerLine
    
    this.moveRect = createSvg(
      "rect",
      {
        class: "move",
        'data-id': "move",
        stroke: "#4982E6",
        'stroke-width': 1,
        'fill-opacity': 0,
        width: rect.width,
        height: rect.height,
        x: 4,
        y: 4
      }
    );
    
    this.topLeftRect = createSvg(
      "rect",
      {
        class: "nw-resize",
        'data-id': "nw-resize",
        fill: "#FFFFFF",
        stroke: "#4982E6",
        'stroke-width': 1,
        width: 6,
        height: 6,
        x: 1,
        y: 1
      }
    );

    this.LeftRect = createSvg(
      "rect",
      {
        class: "w-resize",
        'data-id': "w-resize",
        fill: "#FFFFFF",
        stroke: "#4982E6",
        'stroke-width': 1,
        width: 6,
        height: 6,
        x: 1,
        y: rect.height / 2 + 1
      }
    );

    this.bottomLeftRect = createSvg(
      "rect",
      {
        class: "sw-resize",
        'data-id': "sw-resize",
        fill: "#FFFFFF",
        stroke: "#4982E6",
        'stroke-width': 1,
        width: 6,
        height: 6,
        x: 1,
        y: rect.height + 1
      }
    );

    this.bottomRect = createSvg(
      "rect",
      {
        class: "s-resize",
        'data-id': "s-resize",
        fill: "#FFFFFF",
        stroke: "#4982E6",
        'stroke-width': 1,
        width: 6,
        height: 6,
        x: rect.width / 2 + 1,
        y: rect.height + 1
      }
    );
    
    this.bottomRightRect = createSvg(
      "rect",
      {
        class: "se-resize",
        'data-id': "se-resize",
        fill: "#FFFFFF",
        stroke: "#4982E6",
        'stroke-width': 1,
        width: 6,
        height: 6,
        x: rect.width + 1,
        y: rect.height + 1
      }
    );

    this.rightRect = createSvg(
      "rect",
      {
        class: "e-resize",
        'data-id': "e-resize",
        fill: "#FFFFFF",
        stroke: "#4982E6",
        'stroke-width': 1,
        width: 6,
        height: 6,
        x: rect.width + 1,
        y: rect.height / 2 + 1
      }
    );

    this.topRightRect = createSvg(
      "rect",
      {
        class: "ne-resize",
        'data-id': "ne-resize",
        fill: "#FFFFFF",
        stroke: "#4982E6",
        'stroke-width': 1,
        width: 6,
        height: 6,
        x: rect.width + 1,
        y: 1
      }
    );

    this.topRect = createSvg(
      "rect",
      {
        class: "n-resize",
        'data-id': "n-resize",
        fill: "#FFFFFF",
        stroke: "#4982E6",
        'stroke-width': 1,
        width: 6,
        height: 6,
        x: rect.width / 2 + 1,
        y: 1
      }
    );

    this.outerLine.append(this.moveRect)
    this.outerLine.append(this.topLeftRect)
    this.outerLine.append(this.LeftRect)
    this.outerLine.append(this.bottomLeftRect)
    this.outerLine.append(this.bottomRect)
    this.outerLine.append(this.bottomRightRect)
    this.outerLine.append(this.rightRect)
    this.outerLine.append(this.topRightRect)
    this.outerLine.append(this.topRect)
    this.outerLineContainer.append(this.outerLine)
    this.outerLineContainer.append(this.deletetButton)
    this.initial = true

    if (this.layer.toolMode !== 'form') {
      if (this.annotation.isHidden == 1) {
        this.annotationContainer.style.display = 'none'
        this.annotationContainer.style.pointerEvents = 'none'
      } else if (this.annotation.isHidden == 0) {
        this.annotationContainer.style.display = 'block'
        this.annotationContainer.style.pointerEvents = 'auto'
      }
    }
    if (this.show) {
      !this.layer.addMode && this.selectAnnotation()
      this.show = false
    }
  }

  getActualRect (viewport, s,) {
    const annotation = this.annotation
    const { left: x1, top: y1, right: x2, bottom: y2 } = annotation.rect
    
    const start = getActualPoint(
      {
        x: x1,
        y: y1
      },
      viewport,
      s
    )
    const end = getActualPoint(
      {
        x: x2,
        y: y2
      },
      viewport,
      s
    )
    return {
      start,
      end
    }
  }

  rectCalc ({ start, end }) {
    return {
      top: start.y < end.y ? start.y : end.y,
      left: start.x < end.x ? start.x : end.x,
      width: Math.abs(end.x - start.x),
      height: Math.abs(end.y - start.y),
    };
  };

  calculate (start, end) {
    const initRect = this.rectCalc({ start, end })
    this.initRect = initRect
    const actualBdWidth = (this.annotation.borderWidth || 2) * this.scale

    return {
      top: initRect.top - actualBdWidth,
      left: initRect.left - actualBdWidth,
      width: initRect.width + actualBdWidth * 2,
      height: initRect.height + actualBdWidth * 2,
    }
  }

  getInitialPoint () {
    const s = this.scale
    const startX = this.start.x
    const startY = this.start.y
    const endX = this.end.x
    const endY = this.end.y

    const { width, height, rotation  } = this.viewport;
    let x1, y1, x2, y2;
    if (rotation === 0) {
      x1 = startX / s;
      y1 = startY / s; 
      x2 = endX / s;
      y2 = endY / s;
    } else if (rotation === 90) {
      x1 = startY / s;
      y1 = startX / s;
      x2 = endY / s;
      y2 = endX / s;
    } else if (rotation === 180) {
      x1 =( width - startX) / s;
      y1 = startY / s;
      x2 = (width - endX) / s;
      y2 = endY / s;
    } else {
      x1 = (height - startY) / s
      y1 = (width - startX) / s
      x2 = (height - endY) / s
      y2 = (width - endX)  / s
    }
    return {
      start: {
        x: x1,
        y: y1,
      },
      end: {
        x: x2,
        y: y2,
      },
    };
  }

  updateTool () {
    if (!this.initial) return
    if (this.hidden) {
      if (this.layer.annotationStore.selectedElementName === this.annotation.name) {
        this.layer.selectedElementName = null
      }
      this.outerLineContainer.remove()
    } else {
      if (this.layer.annotationStore.selectedElementName !== this.annotation.name) {
        const annotation = this.annotation
        this.layer.annotationStore.selectedElementName = annotation.name

        const annotationData = {
          ...annotation
        }
        delete annotationData.annotPtr
        delete annotationData.pagePtr
        delete annotationData.operate
        delete annotationData.targetPage

        this.eventBus.dispatch('annotationSelected', annotationData)
      }
      this.container.append(this.outerLineContainer)
      this.outerLine.addEventListener('mousedown', this.onMousedown)
      this.outerLine.addEventListener('touchstart', this.onMousedown)

      this.eventBus.dispatch('propertyChange', this.annotation)

      const documentViewer = this.layer.documentViewer
      const scrollElement = documentViewer.getScrollViewElement()
      scrollElement.style.touchAction = 'none'
    }
  }

  handleClick (event) {
    if (!this.hidden || document.fullscreenElement || this.layer.annotationStore.creating || ['redaction', 'remove'].includes(this.layer.tool) || document.querySelector('.compare-document-container').contains(event?.target)) return
    if (this.layer.toolMode === 'form') {
      this.hidden = false
      this.updateTool()

      this.judgeRadioBtnIsOne()
      
      if (!this.hidden && document.getElementsByClassName('right-panel')[0].className.indexOf('closed') !== -1) {
        document.getElementById('propertyPanelButton').click()
      }

      this.eventBus._on('radioButtonPropertyPanelChanged', this.handlePropertyPanel)
      onClickOutsideUp([this.annotationContainer, this.outerLine, this.deletetButton, document.getElementById('propertyPanelButton'), document.getElementsByClassName('right-panel')[0]], this.handleOutside.bind(this))

    } else {
      this.annotation.isChecked = this.annotation.isChecked == 0 ? 1 : 0
      if (this.annotation.isChecked == 0) {
        this.svgElement.style.display = 'none'
      } else {
        this.svgElement.style.display = 'block'
        this.cancelSameGroupButton()
      }

      const annotation = {
        operate: "mod-form",
        name: this.annotation.name,
        pageIndex: this.page,
        pagePtr: this.annotation.pagePtr,
        annotPtr: this.annotation.annotPtr,
        type: this.annotation.type,
        isChecked: this.annotation.isChecked
      }
      this.eventBus.dispatch('annotationChange', {
        type: 'modify',
        annotation: annotation
      })
      this.getImage()
    }
  }

  selectAnnotation () {
    if (this.layer.selectedElementName === this.annotation.name) return
    this.handleClick()
  }

  handleOutside () {
    if (!this.hidden && this.layer.annotationStore.selectedElementName === this.annotation.name) {
      document.getElementById('propertyPanelButton').click()
    }

    this.hidden = true

    if (this.layer.annotationStore.selectedElementName === this.annotation.name) {
      this.layer.annotationStore.selectedElementName = null
    }
    this.outerLine?.removeEventListener('mousedown', this.onMousedown)
    this.outerLine?.removeEventListener('touchstart', this.onMousedown)
    this.outerLineContainer?.remove()

    const documentViewer = this.layer.documentViewer
    const scrollElement = documentViewer.getScrollViewElement()
    scrollElement.style.touchAction = 'auto'

    this.eventBus._off('radioButtonPropertyPanelChanged', this.handlePropertyPanel)
  }

  handleMouseDown (event) {
    if (this.layer.tool) {
      event.stopPropagation()
    }
    const operatorId = event.target.getAttribute('data-id')

    const documentViewer = this.layer.documentViewer
    const scrollElement = documentViewer.getScrollViewElement()
    this.scrollTop = scrollElement.scrollTop
    this.scrollLeft = scrollElement.scrollLeft

    const { pageX, pageY } = getClickPoint(event)
    this.startState = {
      operator: operatorId,
      clickX: pageX,
      clickY: pageY,
    }

    document.addEventListener('mousemove', this.onMousemove)
    document.addEventListener('mouseup', this.onMouseup)
    document.addEventListener('touchmove', this.onMousemove)
    document.addEventListener('touchend', this.onMouseup)

    this.handleClick()
  };

  handleMouseMove (event) {
    if (event.type === 'touchmove') {
      document.querySelector('.document-container').addEventListener('scroll', event => event.preventDefault())
    }
    this.moving = true
    let { pageX, pageY } = getClickPoint(event)

    const documentViewer = this.layer.documentViewer
    const scrollElement = documentViewer.getScrollViewElement()
    const scrollTop = scrollElement.scrollTop
    const scrollLeft = scrollElement.scrollLeft
    pageX = pageX + scrollLeft - this.scrollLeft
    pageY = pageY + scrollTop - this.scrollTop

    const start = this.start
    const end = this.end
    const startState = this.startState

    const { width, height } = this.viewport
    if (startState.operator === 'nw-resize') {
      let x1 = pageX - (startState.clickX - this.start.x);
      let y1 = pageY - (startState.clickY - this.start.y);
      x1 = Math.min(end.x - 5, x1)
      x1 = Math.max(0, x1)
      y1 = Math.min(end.y - 5, y1)
      y1 = Math.max(0, y1)

      this.update({
        start: { x: x1, y: y1 },
        end,
      });
    } else if (startState.operator === 'w-resize') {
      let x1 = pageX - (startState.clickX - this.start.x);
      x1 = Math.min(end.x - 5, x1)
      x1 = Math.max(0, x1)

      this.update({
        start: { x: x1, y: start.y },
        end,
      });
    } else if (startState.operator === 'sw-resize') {
      let x1 = pageX - (startState.clickX - this.start.x);
      let y1 = pageY - (startState.clickY - this.end.y);
      x1 = Math.min(end.x - 5, x1)
      x1 = Math.max(0, x1)
      y1 = Math.min(height, y1)
      y1 = Math.max(start.y + 5, y1)

      this.update({
        start: { x: x1, y: start.y },
        end: { x: end.x, y: y1 },
      });
    } else if (startState.operator === 's-resize') {
      let y1 = pageY - (startState.clickY - this.end.y);
      y1 = Math.min(height, y1)
      y1 = Math.max(start.y + 5, y1)
      this.update({
        start,
        end: { x: end.x, y: y1 },
      });
    } else if (startState.operator === 'se-resize') {
      let x = pageX - (startState.clickX - this.end.x);
      let y = pageY - (startState.clickY - this.end.y);
      x = Math.min(width, x)
      x = Math.max(start.x + 5, x)
      y = Math.min(height, y)
      y = Math.max(start.y + 5, y)
      this.update({
        start,
        end: { x, y },
      });
    } else if (startState.operator === 'e-resize') {
      let x = pageX - (startState.clickX - this.end.x);
      x = Math.min(width, x)
      x = Math.max(start.x + 5, x)
      this.update({
        start,
        end: { x, y: end.y },
      });
    } else if (startState.operator === 'ne-resize') {
      let x = pageX - (startState.clickX - this.end.x);
      let y = pageY - (startState.clickY - this.start.y);
      x = Math.min(width, x)
      x = Math.max(start.x + 5, x)
      y = Math.min(end.y - 5, y)
      y = Math.max(0, y)
      this.update({
        start: { x: start.x, y },
        end: { x, y: end.y },
      });
    } else if (startState.operator === 'n-resize') {
      let y = pageY - (startState.clickY - this.start.y);
      y = Math.min(end.y - 5, y)
      y = Math.max(0, y)
      this.update({
        start: { x: start.x, y },
        end,
      });
    } else if (startState.operator === 'move') {
      let x1, y1, x2, y2
      const documentViewer = this.layer.documentViewer

      let windowCoordinates = this.getMouseLocation(event);
      const page = documentViewer.getSelectedPage(windowCoordinates, windowCoordinates)
      if (page.first && page.first !== (this.page + 1)) {
        const pagePoint = documentViewer.windowToPage(windowCoordinates, page.first, false)

        const annotationHeight = Math.abs(start.y - end.y)
        x1 = pageX - (startState.clickX - this.start.x)
        y1 = page.first > (this.page + 1) ? pagePoint.y : pagePoint.y - annotationHeight
        x2 = pageX - (startState.clickX - this.end.x)
        y2 = page.first > (this.page + 1) ? pagePoint.y + annotationHeight : pagePoint.y
        this.page = page.first - 1

        this.annotationContainer.remove()
        this.outerLineContainer.remove()
        const container = documentViewer.pdfViewer._pages[this.page].compdfAnnotationLayer.div
        container.append(this.annotationContainer)
        container.append(this.outerLineContainer)

        this.container = container
      } else {
        x1 = pageX - (startState.clickX - this.start.x);
        y1 = pageY - (startState.clickY - this.start.y);
        x2 = pageX - (startState.clickX - this.end.x);
        y2 = pageY - (startState.clickY - this.end.y);

        const windowPoint1 = documentViewer.pageToWindow({
          x: x1,
          y: y1
        }, this.page + 1, false)
        const windowPoint2 = documentViewer.pageToWindow({
          x: x2,
          y: y2
        }, this.page + 1, false)
        let x = 0, y = 0
        if (pageY > startState.clickY) {
          y = scrollElement.offsetHeight - (windowPoint2.y - scrollElement.scrollTop - scrollElement.offsetTop)
          y = y < 100 ? 5 : 0
        } else if (pageY < startState.clickY) {
          y = windowPoint1.y - scrollElement.scrollTop - scrollElement.offsetTop
          y = y < 100 ? -5 : 0
        }
        if (pageX > startState.clickX) {
          x = scrollElement.offsetWidth - (windowPoint2.x - scrollElement.scrollLeft - scrollElement.offsetLeft)
          x = x < 100 ? 5 : 0
        } else if (pageX < startState.clickX) {
          x = (windowPoint1.x - scrollElement.scrollLeft - scrollElement.offsetLeft)
          x = x < 100 ? -5 : 0
        }

        if (x || y) {
          scrollElement.scrollTop += y
          scrollElement.scrollLeft += x
        }

        const rect = {
          width: Math.abs(start.x -end.x),
          height: Math.abs(start.y -end.y)
        }
        if (x1 < x2) {
          x1 = Math.max(0, x1)
          x1 = Math.min(width - rect.width, x1)
          x2 = Math.max(rect.width, x2)
          x2 = Math.min(width, x2)
        } else {
          x2 = Math.max(0, x2)
          x2 = Math.min(width - rect.width, x2)
          x1 = Math.max(rect.width, x1)
          x1 = Math.min(width, x1)
        }

        if (y1 < y2) {
          y1 = Math.max(0, y1)
          y1 = Math.min(height - rect.height, y1)
          y2 = Math.max(rect.height, y2)
          y2 = Math.min(height, y2)
        } else {
          y2 = Math.max(0, y2)
          y2 = Math.min(height - rect.height, y2)
          y1 = Math.max(rect.height, y1)
          y1 = Math.min(height, y1)
        }
      }

      this.update({
        start: { x: x1, y: y1 },
        end: { x: x2, y: y2 },
      });
    }

    startState.clickX = pageX
    startState.clickY = pageY
  }

  handleDelete (event) {
    if (this.layer.tool && event) {
      event.stopPropagation()
    }

    this.delete()
    const annotationData = {
      type: 'delete',
      annotation: {
        operate: "del-annot",
        name: this.annotation.name,
        pageIndex: this.page
      }
    }
    this.annotation.annotPtr && (annotationData.annotation.annotPtr = this.annotation.annotPtr)

    this.eventBus.dispatch('annotationChange', annotationData)
  }

  delete () {
    this.handleOutside()
    this.annotationContainer?.remove()
    this.annotation.isDelete = true
    this.layer.deleteAnnotationInLayer({
      name: this.annotation.name
    })
  }

  handleMouseUp (event) {
    if (this.layer.tool) {
      event.stopPropagation()
    }
    if (event.type === 'touchend') {
      document.querySelector('.document-container').style.overflow = 'auto'
    }
    this.moving = false
    document.removeEventListener('mousemove', this.onMousemove)
    document.removeEventListener('mouseup', this.onMouseup)
    document.removeEventListener('touchmove', this.onMousemove)
    document.removeEventListener('touchend', this.onMouseup)
    this.scrollLeft = 0
    this.scrollTop = 0

    const annotation = this.annotation
    const { start, end } = this.getInitialPoint()

    const rect = {
      left: start.x,
      top: start.y,
      right: end.x,
      bottom: end.y
    }
    if (rect === annotation.rect && annotation.pageIndex === this.page) return

    annotation.rect = rect
    if (annotation.pageIndex !== this.page) {
      const annotationData = {
        type: 'delete',
        annotation: {
          operate: "del-annot",
          name: annotation.name,
          pageIndex: annotation.pageIndex,
          annotPtr: annotation.annotPtr
        }
      }
      this.eventBus.dispatch('annotationChange', annotationData)

      const newAnnotationData = Object.assign({}, annotation)
      delete newAnnotationData.annotPtr
      delete newAnnotationData.pagePtr
      delete newAnnotationData.name
      newAnnotationData.operate = 'add-form'
      newAnnotationData.pageIndex = this.page
      this.eventBus.dispatch('annotationChange', {
        type: 'add',
        show: true,
        annotation: newAnnotationData
      })

      this.annotationContainer.remove()
      this.outerLineContainer.remove()
    } else {
      this.eventBus.dispatch('annotationChange', {
        type: 'modify',
        annotation: {
          operate: "mod-form",
          name: annotation.name,
          pageIndex: this.page,
          pagePtr: annotation.pagePtr,
          annotPtr: annotation.annotPtr,
          rect
        }
      })
      this.getImage(true)
    }
  }

  update ({ start, end }) {
    const rect = this.calculate(start, end)

    this.start = start
    this.end = end

    this.annotationContainer.style.top = rect.top + 'px'
    this.annotationContainer.style.left = rect.left + 'px'
    this.annotationContainer.style.width = rect.width + 'px'
    this.annotationContainer.style.height = rect.height + 'px'
    
    this.annotationContainer.style.width = `${rect.width}px`;
    this.annotationContainer.style.height = `${rect.height}px`;

    this.outerLine.style.left = `${rect.left - 4}px`
    this.outerLine.style.top = `${rect.top - 4}px`
    this.outerLine.style.width = `${rect.width + 4 * 2}px`
    this.outerLine.style.height = `${rect.height + 4 * 2}px`

    const left = (rect.left + rect.width - 30) + 'px'
    const top = (rect.top + rect.height + 8) + 'px'
    this.deletetButton.style.left = left
    this.deletetButton.style.top = top
    
    this.moveRect.setAttribute('width',  rect.width)
    this.moveRect.setAttribute('height',  rect.height)
    
    this.LeftRect.setAttribute("y", rect.height / 2 + 1)

    this.bottomLeftRect.setAttribute("y", rect.height + 1)

    this.bottomRect.setAttribute("x", rect.width / 2 + 1)
    this.bottomRect.setAttribute("y", rect.height + 1)


    this.bottomRightRect.setAttribute("x", rect.width + 1)
    this.bottomRightRect.setAttribute("y", rect.height + 1)


    this.rightRect.setAttribute("x", rect.width + 1)
    this.rightRect.setAttribute("y", rect.height / 2 + 1)

    
    this.topRightRect.setAttribute("x", rect.width + 1)

    this.topRect.setAttribute("x", rect.width / 2 + 1)

    this.svgElement.style.width = `${rect.width / 2}px`
    this.svgElement.style.height = `${rect.height / 2}px`
  }

  handlePropertyPanel (props) {
    if (this.layer.annotationStore.selectedElementName !== this.annotation.name) return
    let updatePropsNum = 0
    for (const key in props) {
      for (const item in this.annotation) {
        if (item === key && this.annotation[item] !== props[key]) {
          this.annotation[item] = props[key]
          updatePropsNum ++

          if (key === 'backgroundColor') {
            this.borderElement.style[key] = props[key]
            if (props[key] === '') {
              props.clearBackgroundColor = true
            }
          }
          if (key === 'checkStyle') {
            this.svgElement.removeChild(this.svgElement.firstChild)
            this.setSelectedShape(props[key])
          }
          if (key === 'isChecked') {
            if (props[key]) {
              this.svgElement.style.display = 'block'
              this.cancelSameGroupButton()
            } else {
              this.svgElement.style.display = 'none'
            }
          }
          if (key === 'fieldName') {
            this.judgeRadioBtnIsOne()
          }
        }
      }
    }

    if (updatePropsNum > 0) {
      const annotation = {
        operate: "mod-form",
        name: this.annotation.name,
        pageIndex: this.page,
        pagePtr: this.annotation.pagePtr,
        annotPtr: this.annotation.annotPtr,
        type: this.annotation.type
      }
      const updateAnnot = Object.assign({}, annotation, props)
      this.eventBus.dispatch('annotationChange', {
        type: 'modify',
        annotation: updateAnnot
      })
      this.getImage()
    }
  }

  setSelectedShape (val) {
    if (val === 1) {
      this.svgElement.setAttribute('width', '14')
      this.svgElement.setAttribute('height', '14')
      this.svgElement.setAttribute('viewBox', '0 0 14 14')
      this.svgElement.append(this.circlePath)
    } else if (val === 2) {
      this.svgElement.setAttribute('width', '12')
      this.svgElement.setAttribute('height', '12')
      this.svgElement.setAttribute('viewBox', '0 0 12 12')
      this.svgElement.append(this.crossPath)
    } else if (val === 3) {
      this.svgElement.setAttribute('width', '15')
      this.svgElement.setAttribute('height', '15')
      this.svgElement.setAttribute('viewBox', '0 0 15 15')
      this.svgElement.append(this.diamondPath)
    } else if (val === 4) {
      this.svgElement.setAttribute('width', '12')
      this.svgElement.setAttribute('height', '12')
      this.svgElement.setAttribute('viewBox', '0 0 12 12')
      this.svgElement.append(this.squarePath)
    } else if (val === 5) {
      this.svgElement.setAttribute('width', '16')
      this.svgElement.setAttribute('height', '15')
      this.svgElement.setAttribute('viewBox', '0 0 16 15')
      this.svgElement.append(this.starPath)
    } else {
      this.svgElement.setAttribute('width', '15')
      this.svgElement.setAttribute('height', '15')
      this.svgElement.setAttribute('viewBox', '0 0 15 12')
      this.svgElement.append(this.checkPath)
    }
  }

  setProperty (props) {
    if (props.name !== this.annotation.name) return

    for (const key in props) {
      for (const item in this.annotation) {
        if (item === key && this.annotation[item] !== props[key]) {
          this.annotation[item] = props[key]

          if (key === 'backgroundColor') {
            this.borderElement.style[key] = props[key]
          }
          if (key === 'checkStyle') {
            this.svgElement.removeChild(this.svgElement.firstChild)
            this.setSelectedShape(props[key])
          }
          if (key === 'isChecked') {
            if (props[key] == 0) {
              this.svgElement.style.display = 'none'
            } else {
              this.svgElement.style.display = 'block'
              this.cancelSameGroupButton()
            }
          }
          if (key === 'fieldName') {
            this.judgeRadioBtnIsOne()
          }
        }
      }
    }

    const annotation = {
      operate: "mod-form",
      pageIndex: this.page,
      pagePtr: this.annotation.pagePtr,
      annotPtr: this.annotation.annotPtr,
      type: this.annotation.type
    }
    const updateAnnot = Object.assign({}, annotation, props)
    this.eventBus.dispatch('annotationChange', {
      type: 'modify',
      annotation: updateAnnot
    })
    this.getImage()
  }

  cancelSameGroupButton () {
    let annotationsAll = Object.values(this.layer.annotationStore.annotationsAll).reduce(function(acc, curr) {
      return acc.concat(curr)
    }, [])
    let sameGroupArr = annotationsAll.filter(obj => obj.fieldName === this.annotation.fieldName && obj.name !== this.annotation.name && obj.isChecked != 0 && obj.type === 'radiobutton')
    for (const item of sameGroupArr) {
      this.eventBus.dispatch('handleField', {
        id: item.name,
        key: 'isChecked',
        value: 0
      })
    }
  }

  judgeRadioBtnIsOne () {
    let annotationsAll = Object.values(this.layer.annotationStore.annotationsAll).reduce(function(acc, curr) {
      return acc.concat(curr)
    }, [])
    let isOne = true
    for (const item of annotationsAll) {
      if (item.hasOwnProperty('fieldName')) {
        if (item.fieldName === this.annotation.fieldName && item.name !== this.annotation.name && item.type === 'radiobutton') {
          isOne = false
          break
        }
      }
    }
    this.eventBus.dispatch('judgeRadioBtnIsOne', isOne)
  }

  setHighlight (bool) {
    this.highlight = bool
    this.annotationContainer.style.backgroundColor = this.highlight ? '#4982E54D' : ''
  }

  async getImage(update) {
    const rect = this.initRect
    const imgRect = {
      width: parseInt(rect.width * this.layer.ratio + 1),
      height: parseInt(rect.height * this.layer.ratio + 1)
    }

    const imageArray = await this.messageHandler.sendWithPromise('GetRenderAnnot', {
      annotPtr: this.annotation.annotPtr,
      width: imgRect.width,
      height: imgRect.height
    })

    const canvas = document.createElement('canvas')
    canvas.style.width = imgRect.width + 'px'
    canvas.style.height = imgRect.height + 'px'
    canvas.width = imgRect.width
    canvas.height = imgRect.height
    let drawContext = canvas.getContext("2d")
    drawContext.clearRect(0, 0, canvas.width, canvas.height)
    let imageData = drawContext.createImageData(imgRect.width, imgRect.height)
    imageData.data.set(imageArray)
    drawContext.putImageData(imageData, 0, 0)
    const imgSrc = canvas.toDataURL("image/png", 1)

    if (update) {
      const rect = this.calculate(this.start, this.end)
      this.shapeElement.style.width = `${rect.width}px`
      this.shapeElement.style.height = `${rect.height}px`
    }

    if (this.imgEle) {
      this.imgEle.src = imgSrc
    } else {
      let imgEle = document.createElement('img')
      imgEle.style.width = '100%'
      imgEle.style.height = '100%'
      imgEle.style.pointerEvents = 'none'

      imgEle.src = imgSrc
      this.imgEle = imgEle

      this.shapeElement.append(this.imgEle)
    }
  }
}
