import {
  getAbsoluteCoordinate,
  createElement,
  getInitialPoint
} from '../annotation/utils'

export default class AddImage {
  constructor ({
    tool,
    color,
    container,
    pageViewer,
    viewport,
    page,
    eventBus,
    contentContainer,
    $t
  }) {
    this._tool = tool
    this.color = color
    this.container = container
    this.pageViewer = pageViewer
    this.viewport = viewport
    this.page = page
    this.eventBus = eventBus
    this.contentContainer = contentContainer
    this.$t = $t

    this.path = []
    this.initStartPoint = null
    this.initEndPoint = null
    this.shapeEle = null

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

    this.init()
  }

  init () {
    this.container.addEventListener('mousedown', this.onMousedown)
    this.container.addEventListener('touchstart', this.onMousedown)
    this.container.style.cursor = 'crosshair'
    this.container.style.touchAction = 'none'
    document.removeEventListener('mousemove', this.onMousemove)
    document.removeEventListener('mouseup', this.onMouseup)
    document.removeEventListener('touchmove', this.onMousemove)
    document.removeEventListener('touchend', this.onMouseup)
  }

  get tool () {
    return this._tool
  }

  set tool (toolType) {
    if (toolType === this._tool) return
    if (!toolType) {
      this.reset()
      this.container.style.cursor = 'default'
      this.container.style.touchAction = ''

      this.container.removeEventListener('mousedown', this.onMousedown)
      this.container.removeEventListener('touchstart', this.onMousedown)
    }
    this._tool = toolType
  }

  reset () {
    this.initStartPoint = null
    this.initEndPoint = null
    if (this.shapeEle) this.shapeEle.remove()
    this.shapeEle = null
    this.path = []
    document.removeEventListener('mousemove', this.onMousemove)
    document.removeEventListener('mouseup', this.onMouseup)
    
    document.removeEventListener('touchmove', this.onMousemove)
    document.removeEventListener('touchend', this.onMouseup)

    this.container.removeEventListener('mousedown', this.onMousedown)
    this.container.removeEventListener('touchstart', this.onMousedown)
  }

  handleMouseDown (event) {
    if (this.contentContainer.selectedFrameIndex !== -1) return
    if (!event.target.className && !event.target.className.includes('contentContainer')) return
    if (event.target.className?.includes('image-container')) return
    
    const { x, y } = getAbsoluteCoordinate(this.container, event)
    this.initStartPoint = { x, y }

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

  handleMouseUp () {
    const initStartPoint = this.initStartPoint
    const initEndPoint = this.initEndPoint

    if (initEndPoint && initStartPoint.x !== initEndPoint.x && initStartPoint.y !== initEndPoint.y) { // 绘制区域
      const start = getInitialPoint(initStartPoint, this.pageViewer.viewport, this.pageViewer.viewport.scale)
      const end = getInitialPoint(initEndPoint, this.pageViewer.viewport, this.pageViewer.viewport.scale)
      
      const newStart = {
        x: Math.min(start.x, end.x),
        y: Math.min(start.y, end.y)
      }
      const newEnd = {
        x: Math.max(start.x, end.x),
        y: Math.max(start.y, end.y)
      }
      
      const area = {
        left: newStart.x,
        top: newStart.y,
        right: newEnd.x,
        bottom: newEnd.y,
        width: newEnd.x - newStart.x,
        height: newEnd.y - newStart.y
      }

      this.uploadFile()
        .then((data) => {
          const { imageBase64, width, height } = data

          const imageRatio = width / height
          const rectRatio = area.width / area.height
          let scaledWidth, scaledHeight

          if (imageRatio > rectRatio) {
            scaledWidth = area.width
            scaledHeight = area.width / imageRatio
          } else {
            scaledWidth = area.height * imageRatio
            scaledHeight = area.height
          }
          
          const centerPoint = {
            x: area.left + area.width / 2,
            y: area.top + area.height / 2
          }

          const rect = {
            left: centerPoint.x - scaledWidth / 2,
            top: centerPoint.y - scaledHeight / 2,
            right: centerPoint.x + scaledWidth / 2,
            bottom: centerPoint.y + scaledHeight / 2,
          }

          this.contentContainer.addImageEditor({
            rect,
            imageBase64
          })
        })
        .catch((error) => {
          console.error(error)
        })
    } else { // 单击区域
      const centerPoint = getInitialPoint(initStartPoint, this.pageViewer.viewport, this.pageViewer.viewport.scale)
      const pageWidth = this.pageViewer.viewport.viewBox[2]
      const pageHeight = this.pageViewer.viewport.viewBox[3]
      const fixedWidth = pageWidth / 2
      const fixedHeight = pageHeight / 2

      this.uploadFile()
        .then((data) => {
          const { imageBase64, width, height } = data

          let scaledWidth = width
          let scaledHeight = height

          if (width > fixedWidth || height > fixedHeight) {
            const imageRatio = width / height
            const rectRatio = fixedWidth / fixedHeight
      
            if (imageRatio > rectRatio) {
              scaledWidth = fixedWidth
              scaledHeight = fixedWidth / imageRatio
            } else {
              scaledWidth = fixedHeight * imageRatio
              scaledHeight = fixedHeight
            }
          }

          const rect = {
            left: centerPoint.x - scaledWidth / 2,
            top: centerPoint.y - scaledHeight / 2,
            right: centerPoint.x + scaledWidth / 2,
            bottom: centerPoint.y + scaledHeight / 2,
          }

          if (rect.left < 7) {
            const offset = 7 - rect.left
            rect.left += offset
            rect.right += offset
          }
          if (rect.top < 7) {
            const offset = 7 - rect.top
            rect.top += offset
            rect.bottom += offset
          }
          if (rect.right > pageWidth) {
            const offset = rect.right - pageWidth + 7
            rect.right -= offset
            rect.left -= offset
          }
          if (rect.bottom > pageHeight) {
            const offset = rect.bottom - pageHeight + 7
            rect.bottom -= offset
            rect.top -= offset
          }

          this.contentContainer.addImageEditor({
            rect,
            imageBase64
          })
        })
        .catch((error) => {
          console.error(error)
        })
    }

    // this.reset()
    this.initStartPoint = null
    this.initEndPoint = null
    if (this.shapeEle) this.shapeEle.remove()
    this.shapeEle = null
    this.path = []
    document.removeEventListener('mousemove', this.onMousemove)
    document.removeEventListener('mouseup', this.onMouseup)
    
    document.removeEventListener('touchmove', this.onMousemove)
    document.removeEventListener('touchend', this.onMouseup)
  }

  handleMouseMove (event) {
    let { x, y } = getAbsoluteCoordinate(this.container, event)
    const { width, height } = this.pageViewer.viewport
    const scale = this.pageViewer.viewport.scale
    x = Math.min(width, x)
    x = Math.max(0, x)
    y = Math.min(height, y)
    y = Math.max(0, y)
    this.initEndPoint = { x, y }
    if (this.initStartPoint.x !== this.initEndPoint.x && this.initStartPoint.y !== this.initEndPoint.y) {
      if (!this.shapeEle) {
        const shapeEle = createElement('div', {
          'backgroundColor': '#DDE9FF',
          'position': "absolute",
          'z-index': 3
        },
        {
          class: 'add-text'
        })
        this.shapeEle = shapeEle
        this.container.append(this.shapeEle)
      } else {
        if (event.shiftKey) {
          const { initStartPoint, initEndPoint } = this
          const distanceX = Math.abs(initEndPoint.x - initStartPoint.x)
          const distanceY = Math.abs(initEndPoint.y - initStartPoint.y)
          const distance = Math.min(distanceX, distanceY)
          if (initStartPoint.x < initEndPoint.x) {
            initEndPoint.x = initStartPoint.x + distance
          } else {
            initEndPoint.x = initStartPoint.x - distance
          }
          if (initStartPoint.y < initEndPoint.y) {
            initEndPoint.y = initStartPoint.y + distance
          } else {
            initEndPoint.y = initStartPoint.y - distance
          }
        }
        const rect = this.calculate(this.initStartPoint, this.initEndPoint)

        const shapeEle = this.shapeEle
        shapeEle.style.top = `${rect.top}px`
        shapeEle.style.left = `${rect.left}px`
        shapeEle.style.width = `${Math.abs(rect.width - 1)}px`
        shapeEle.style.height = `${Math.abs(rect.height - 1)}px`
      }
    }
  }
  
  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 })
    const actualbdwidth = 1 * this.pageViewer.viewport.scale

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

  // 上传图片并获取宽高
  uploadFile () {
    return new Promise((resolve, reject) => {
      const fileInput = document.createElement('input')
      fileInput.type = 'file'
      fileInput.accept = '.jpg, .jpeg, .png'

      fileInput.onchange = () => {
        const file = fileInput.files[0]

        if (file.size > 2 * 1024 * 1024) {
          reject(this.$t('editorPanel.maximum'))
          fileInput.remove()
          window.$message.error(this.$t('editorPanel.maximum'), {
            duration: 3000,
            // icon: () => h('img', { src: MessageError })
          })
          return
        }

        if (file) {
          const reader = new FileReader()
          reader.onload = function (e) {
            const image = new Image()
            image.onload = function () {
              resolve({
                // file,
                imageBase64: e.target.result,
                width: image.width,
                height: image.height
              })
            }
            image.onerror = function (error) {
              reject(error)
            }
            image.src = e.target.result
          }
          reader.onerror = function (error) {
            reject(error)
          }
          reader.readAsDataURL(file)
          fileInput.remove()
        }
      }
      fileInput.click()
    })
  }
}
