import { getInitialPoint } from './annotation/utils';
import { isMobile } from './ui_utils';

class Signatures {
  constructor({ pdfViewer, eventBus, type }) {
    this.pdfViewer = pdfViewer
    this.eventBus = eventBus
    this.type = type // 0: electronic signature, 1: digital signature

    this.path = []
    this.inkPath = []
    this.currentPath = []
    this.areaBound = [NaN, NaN, NaN, NaN]
    this.inkPadding = { x: 10, y: 10 }
    this.strokeWidth = 5
    this.strokColor = "#000"

    this.onMousedown = this.handleMouseDown.bind(this)
    this.onMousemove = this.handleMouseMove.bind(this)
    this.onMouseup = this.handleMouseUp.bind(this)
    this.onHandleGetSignData = this.getData.bind(this)
    this.onHandleInitCursorStyle = this.initCursorStyle.bind(this)
    this.init()
  }

  init() {
    const digitalTrackpadCanvas = document.getElementById('digitalTrackpadCanvas')
    const electronicTrackpadCanvas = document.getElementById('electronicTrackpadCanvas')

    this.canvas = this.type ? digitalTrackpadCanvas : electronicTrackpadCanvas
    this.ctx = this.canvas.getContext('2d')
    this.canvas.style.cursor = 'crosshair'

    this.canvas.addEventListener('mousedown', this.onMousedown)
    this.canvas.addEventListener('touchstart', this.onMousedown)

    this.eventBus._on('getSignData', this.onHandleGetSignData)
    this.eventBus._on('initCursorStyle', this.onHandleInitCursorStyle)
  }

  handleMouseDown(e) {
    if (e.changedTouches && e.changedTouches.length !== 1) return
    const clientX = e.clientX || e.changedTouches[0].clientX
    const clientY = e.clientY || e.changedTouches[0].clientY

    //计算鼠标在画布的距离
    let disX, disY
    if (isMobile && this.type) { // 横屏
      disX = clientY - this.canvas.getBoundingClientRect().top
      disY = this.canvas.height - (clientX - this.canvas.getBoundingClientRect().left)
    } else {
      disX = clientX - this.canvas.getBoundingClientRect().left
      disY = clientY - this.canvas.getBoundingClientRect().top
    }
    
    //设置画线的宽，与颜色
    this.ctx.lineWidth = this.strokeWidth
    this.ctx.strokeStyle = this.strokColor
    this.ctx.lineJoin = 'round'
    this.ctx.lineCap = 'round'

    if (this.currentPath.length > 0) {
      this.inkPath.push(this.currentPath)
      this.currentPath = []
    }
    this.ctx.beginPath()
    //设置画的起始点
    this.ctx.moveTo(disX, disY)
    this.mousedown = true
    this.pressPoint = { x: disX, y: disY }
    document.addEventListener('mousemove', this.onMousemove)
    document.addEventListener('mouseup', this.onMouseup)
    document.addEventListener('touchmove', this.onMousemove)
    document.addEventListener('touchend', this.onMouseup)
  }

  handleMouseMove(e) {
    const clientX = e.clientX || e.changedTouches[0].clientX
    const clientY = e.clientY || e.changedTouches[0].clientY

    let disX, disY
    if (isMobile && this.type) { // 横屏
      disX = clientY - this.canvas.getBoundingClientRect().top
      disY = this.canvas.height - (clientX - this.canvas.getBoundingClientRect().left)
    } else {
      disX = clientX - this.canvas.getBoundingClientRect().left
      disY = clientY - this.canvas.getBoundingClientRect().top
    }

    if (!(disX > this.canvas.width || disY > this.canvas.height || disX < 0 || disY < 0)) {
      // 移动时设置画线的结束位置并显示
      let savePoint = true
      if (this.mousedown) {
        if (this.pressPoint && (disX == this.pressPoint.x && disY == this.pressPoint.y)) { // 避免保存只单击一个点
          savePoint = false
        }
      }

      if (savePoint) {
        this.ctx.lineTo(disX, disY) // 鼠标点下去的位置
        this.ctx.stroke()
        this.path.push([disX, disY])
        this.currentPath.push({ x: disX, y: disY })
      }
    }
  }

  handleMouseUp() {
    document.removeEventListener('mousemove', this.onMousemove)
    document.removeEventListener('mouseup', this.onMouseup)
    document.removeEventListener('touchmove', this.onMousemove)
    document.removeEventListener('touchend', this.onMouseup)
    this.mousedown = false
    this.pressPoint = { x: -1, y: -1 }
    const rect = this.getRect()
    this.rect = rect
    if (this.currentPath.length > 0) {
      this.inkPath.push(this.currentPath)
      this.currentPath = []
    }
  }

  clear() {
    this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)
    this.path = []
    this.inkPath = []
    this.currentPath = []
    this.areaBound = [NaN, NaN, NaN, NaN]
    this.initCursorStyle()
  }

  reset() {
    this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)
    this.path = []
    this.inkPath = []
    this.currentPath = []
    this.areaBound = [NaN, NaN, NaN, NaN]
    this.onMousedown = null
    this.onMousemove = null
    this.onMouseup = null
    this.onHandleGetSignData = null
    this.onHandleInitCursorStyle = null
  }

  getRect() {
    const xArray = []
    const yArray = []
    this.path.forEach((point) => {
      xArray.push(point[0])
      yArray.push(point[1])
    })
    const top = Math.min(...yArray)
    const left = Math.min(...xArray)
    const bottom = Math.max(...yArray)
    const right = Math.max(...xArray)
    // this.addPath = this.addPath.map((ele) => {
    //   let x = ele[0] - left
    //   let y = ele[1] - top
    //   return [x, y]
    // })
    return {
      left,
      top,
      bottom,
      right,
      width: right - left,
      height: bottom - top
    }
  }

  getImageBase64() {
    let imageBase64 = null
    if (this.path.length !== 0){
      let finalCanvas = this.getInkPathData()
      imageBase64 = finalCanvas.toDataURL('image/png')
      if (!finalCanvas) {
        finalCanvas = this.paintFinalCanvas()
        imageBase64 = finalCanvas.toDataURL('image/jpeg')
      }
    }
    return imageBase64
  }

  async toImage(param) {
    let { annotation, imageBase64 } = param
    const { annotPtr, rect, pagePtr } = annotation
    let dataURL = null

    if (this.path.length !== 0){
      let finalCanvas = this.getInkPathData()
      let imageUrl = finalCanvas.toDataURL('image/png')
      if (!finalCanvas) {
        finalCanvas = this.paintFinalCanvas()
        imageUrl = finalCanvas.toDataURL('image/jpeg')
      }
      dataURL = imageUrl
    }
    this.dataURL = dataURL || imageBase64
    const imageArray = dataURL ? this.dataURLToArrayBuffer(dataURL) : null

    if (annotPtr && (imageArray || imageBase64) && !this.type) {
      this.eventBus.dispatch('updateSignatureAp', {
        type: this.type,
        annotPtr,
        pagePtr,
        rect,
        imageArray,
        imageBase64,
        annotation
      })
    }

    // if (this.type) {
    //   const previewContainer = document.querySelector('#digitalSignaturePreview')
    //   previewContainer.querySelector('img').src = dataURL
    //   return
    // }

    // 创建一个Image元素
    // var img = new Image()
    // img.src = dataURL
    // img.id = 'sign-image-save'

    // // 设置样式和光标
    // img.style.position = "fixed"
    // img.style.pointerEvents = "none"
    // img.style.zIndex = "5"
    // img.classList.add('sign-ink-save')

    // if (isSaveInk) {
    //   Object.defineProperty(img, 'inkPath', { value: this.inkPath })
    //   Object.defineProperty(img, 'inkParam', { value: param })
    // }

    // let documentContainer = document.querySelector('.document-container')

    // const rect = this.rect

    // documentContainer.addEventListener("mousemove", function (event) {
    //   // 获取光标的位置
    //   var x = event.clientX
    //   var y = event.clientY

    //   let offsetX = rect.width / 2
    //   let offsetY = rect.height / 2

    //   // 设置图片的位置
    //   img.style.left = (x - offsetX) + "px"
    //   img.style.top = (y - offsetY) + "px"
    // })

    // // 移动端 添加图片至页面中心
    // var isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
    // var targetPage = document.querySelector('.page.page-number' + this.pdfViewer.currentPageNumber)
    // if (isMobile) {
    //   var targetPageRect = targetPage.getBoundingClientRect()

    //   var x = targetPageRect.left + targetPageRect.width / 2
    //   var y = targetPageRect.top + targetPageRect.height / 2

    //   let offsetX = rect.width / 2
    //   let offsetY = rect.height / 2

    //   img.style.left = (x - offsetX) + "px"
    //   img.style.top = (y - offsetY) + "px"
    // }

    // this.img = img

    // // 添加图片到页面
    // documentContainer.appendChild(this.img)
    // this.documentContainer = documentContainer

    // // 移动端 调用点击事件直接添加到页面
    // setTimeout(() => {
    //   if (isMobile) {
    //     var event = new PointerEvent('click')
    //     targetPage.dispatchEvent(event)
    //   }
    // }, 10)
  }

  getData(layerData) {
    if (this.path.length === 0) return
    this.layerData = layerData
    // const annotation = {
    //   operate: "add-annot",
    //   type: 'ink',
    //   pageIndex: this.layerData.page + 1,
    //   lineWidth: 2,
    //   transparency: 0.8,
    //   borderColor: '#000000',
    //   arrow: false,
    // }
    const annotation = {
      operate: "add-annot",
      type: "image",
      pageIndex: this.layerData.page + 1,
      imageBase64: this.dataURL,
      date: new Date(),
      // targetPage: pageNum,
      // date: new Date(),
      // name: uuidv4()
    }
    const { path, rect } = this.formatPath()

    annotation.rect = rect
    // annotation.inklist = path

    this.eventBus.dispatch('createSignature', annotation)
  }

  calcInkPath() {
    if (this.inkPath.length > 0) {
      for (let i = 0; i < this.inkPath.length; i++) {
        for (let j = 0; j < this.inkPath[i].length; j++) {
          if (isNaN(this.areaBound[0])) {
            this.areaBound[0] = this.inkPath[i][j].x
            this.areaBound[1] = this.inkPath[i][j].y
            this.areaBound[2] = this.inkPath[i][j].x
            this.areaBound[3] = this.inkPath[i][j].y
            continue;
          }

          if (this.areaBound[0] > this.inkPath[i][j].x) {
            this.areaBound[0] = this.inkPath[i][j].x
          }

          if (this.areaBound[1] > this.inkPath[i][j].y) {
            this.areaBound[1] = this.inkPath[i][j].y
          }

          if (this.areaBound[2] < this.inkPath[i][j].x) {
            this.areaBound[2] = this.inkPath[i][j].x
          }

          if (this.areaBound[3] < this.inkPath[i][j].y) {
            this.areaBound[3] = this.inkPath[i][j].y
          }
        }
      }

      if (!isNaN(this.areaBound[0])) {

        let offset = { x: this.inkPadding.x - this.areaBound[0], y: this.inkPadding.y - this.areaBound[1] }

        for (let i = 0; i < this.inkPath.length; i++) {
          for (let j = 0; j < this.inkPath[i].length; j++) {
            this.inkPath[i][j].x = this.inkPath[i][j].x + offset.x
            this.inkPath[i][j].y = this.inkPath[i][j].y + offset.y
          }
        }
      }
    }
  }

  getInkPathData() {
    this.calcInkPath()
    if (!isNaN(this.areaBound[0])) {
      let drawCanvas = document.createElement("canvas")
      let drawContext = drawCanvas.getContext("2d")

      drawCanvas.width = this.areaBound[2] - this.areaBound[0] + this.inkPadding.x * 2
      drawCanvas.height = this.areaBound[3] - this.areaBound[1] + this.inkPadding.y * 2
      drawContext.strokeStyle = this.strokColor
      drawContext.lineWidth = this.strokeWidth

      for (let i = 0; i < this.inkPath.length; i++) {
        if (this.inkPath[i].length == 1) {
          drawContext.beginPath()
          drawContext.fillStyle = this.strokColor
          drawContext.ellipse(this.inkPath[i][0].x, this.inkPath[i][0].y, this.strokeWidth / 2, this.strokeWidth / 2, 0, 0, 360, false)
          drawContext.fill()
          drawContext.closePath()
        }

        if (this.inkPath[i].length > 1) {
          drawContext.beginPath()
          drawContext.moveTo(this.inkPath[i][0].x, this.inkPath[i][0].y)
          for (let j = 1; j < this.inkPath[i].length; j++) {
            drawContext.lineTo(this.inkPath[i][j].x, this.inkPath[i][j].y)
          }
          drawContext.stroke()
          drawContext.closePath()
        }
      }
      return drawCanvas
    }
    return null
  }

  formatPath() {
    let path = ''
    const length = this.path.length

    const xArray = [];
    const yArray = [];

    for (let i = 0; i < length; i = i + 2) {
      const point = this.handlePoint(this.path[i])

      xArray.push(point.x);
      yArray.push(point.y);

      path += (point.x.toFixed(2) + ',' + point.y.toFixed(2))
      if (i + 1 < length) {

        const point = this.handlePoint(this.path[i])

        xArray.push(point.x);
        yArray.push(point.y);

        path += (';' + point.x.toFixed(2) + ',' + point.y.toFixed(2))
        if (i + 2 < length) {
          path += ';'
        }
      }
    }

    const left = Math.min(...xArray);
    const bottom = Math.min(...yArray);
    const right = Math.max(...xArray);
    const top = Math.max(...yArray);

    return {
      path,
      rect: `${left},${bottom},${right},${top}`
    }
  }

  handlePoint(point) {
    const newPoint = getInitialPoint(
      {
        x: point[0] + this.layerData.clickX - this.rect.width / 2,
        y: point[1] + this.layerData.clickY - this.rect.height / 2
      },
      this.layerData.viewport,
      this.layerData.viewport.scale
    )
    return {
      x: newPoint.x,
      y: newPoint.y
    }
  }

  initCursorStyle() {
    if (this.img) {
      this.img.remove()
    }
  }

  paintFinalCanvas() {
    let finalCanvas = document.createElement("canvas")
    let ctx = finalCanvas.getContext('2d')

    finalCanvas.width = this.rect.width
    finalCanvas.height = this.rect.height

    ctx.fillStyle = 'white'
    ctx.fillRect(0, 0, finalCanvas.width, finalCanvas.height)
    ctx.lineWidth = 3;
    ctx.strokeStyle = 'black';

    ctx.drawImage(this.canvas, this.rect.left, this.rect.top, finalCanvas.width, finalCanvas.height, 0, 0, finalCanvas.width, finalCanvas.height)

    return finalCanvas
  }

  async update(param) {
    if (this.type) {
      await this.toImage(param)
    }

    const { width, color } = param
    width && (this.strokeWidth = width)
    color && (this.strokColor = color)

    if (this.inkPath) {
      this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)
      this.ctx.lineWidth = this.strokeWidth
      this.ctx.strokeStyle = this.strokColor

      for (let i = 0; i < this.inkPath.length; i++) {
        if (this.inkPath[i].length == 1) {
          this.ctx.beginPath()
          this.ctx.fillStyle = this.strokColor
          this.ctx.ellipse(this.inkPath[i][0].x, this.inkPath[i][0].y, this.strokeWidth / 2, this.strokeWidth / 2, 0, 0, 360, false)
          this.ctx.fill()
          this.ctx.closePath()
        }

        if (this.inkPath[i].length > 1) {
          this.ctx.beginPath()
          this.ctx.moveTo(this.inkPath[i][0].x, this.inkPath[i][0].y)
          for (let j = 1; j < this.inkPath[i].length; j++) {
            this.ctx.lineTo(this.inkPath[i][j].x, this.inkPath[i][j].y)
          }
          this.ctx.stroke()
          this.ctx.closePath()
        }
      }
    }
  }

  dataURLToArrayBuffer(dataURL) {
    var binary = atob(dataURL.split(',')[1])
    var mime = dataURL.split(';')[0].split(':')[1]
    var arrayBuffer = new ArrayBuffer(binary.length)
    var uintArray = new Uint8Array(arrayBuffer)
    for (var i = 0; i < binary.length; i++) {
      uintArray[i] = binary.charCodeAt(i)
    }
    return uintArray
  }

  updateSignature(signature) {}
}

export { Signatures }
