import BaseAnnotation from '../annotation/base'
import { hexToRgb, onClickOutside } from '../ui_utils'
import { createSvg, createElement } from '../annotation/utils'
import { getActualPoint } from '../annotation/utils'
import Color from '../color';

class TextAnnotation extends BaseAnnotation {
  constructor ({
    container,
    annotation,
    page,
    viewport,
    scale,
    eventBus,
    layer,
    show = false
  }) {
    super({
      container,
      annotation,
      page,
      viewport,
      scale,
      eventBus,
      show
    })
    this.layer = layer
    this.hidden = true
    this.markupContainer = null
    this.outerLineContainer = null

    this.onHandleClick = this.handleClick.bind(this)
    this.onDelete = this.handleDelete.bind(this)
    this.onOpenReply = this.openReply.bind(this)

    this.render()
  }

  render () {
    const annotation = this.annotation
    const scale = this.scale

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

    const rect = this.calculate(start, end)

    const quadPoints = annotation.quadPoints
    if (!quadPoints) return

    let positionArray = []
    for (let i = 0; (i + 3) < quadPoints.length; i+=4) {
      const x1 = parseInt(quadPoints[i].PointX * scale, 10),
        y1 = parseInt(quadPoints[i].PointY * scale, 10),
        x2 = parseInt(quadPoints[i + 1].PointX * scale, 10),
        y3 = parseInt(quadPoints[i + 2].PointY * scale, 10)
      const left = Math.min(x1, x2)
      const right = Math.max(x1, x2)
      const top = Math.min(y1, y3)
      const bottom = Math.max(y1, y3)
      const width = parseInt(right - left)
      const height = parseInt(bottom - top)
      positionArray.push({
        left,
        top,
        width,
        height
      })
    }

    if (annotation.type === 'highlight') {
      this.renderHighlight(positionArray)
    } else if (annotation.type === 'underline') {
      this.renderUnderline(positionArray)
    } else if (annotation.type === 'squiggly') {
      this.renderSquiggly(positionArray)
    } else if (annotation.type === 'strikeout') {
      this.renderStrikeout(positionArray)
    }
    this.markupContainer.addEventListener('click', this.onHandleClick)
    
    this.outerLineContainer = document.createElement('div')
    this.outerLineContainer.className = 'outline-container'

    const rectContainer = createSvg(
      "svg"
    )
    rectContainer.style.left = (rect.left - 6) + 'px'
    rectContainer.style.top = (rect.top - 6) + 'px'
    rectContainer.style.width = (rect.width + 12) + 'px'
    rectContainer.style.height = (rect.height + 12) + 'px'

    const recttangle = createSvg(
      "rect", {
        x: 3,
        y: 3,
        width: rect.width + 6,
        height: rect.height + 6,
        fill: '#ffffff',
        'fill-opacity': 0,
        'stroke-width': 1,
        stroke: '#1460F3'
      }
    )
    rectContainer.append(recttangle)

    const deletetButton = createSvg(
      "svg",
      {
        width: "30",
        height: "30",
        viewBox: "0 0 30 30",
        fill: "none",
        class: 'delete-button'
      },
      {
        width: '30px',
        height: '30px'
      }
    )
    deletetButton.addEventListener('click', this.onDelete)
    deletetButton.innerHTML = this.deleteSvgStr
    deletetButton.style.left = (rect.left + rect.width - 30) + 'px'
    deletetButton.style.top = (rect.top + rect.height + 8) + 'px'

    this.replyButton = createElement(
      'div',
      {
        width: '30px',
        height: '30px',
        background: '#DDE9FF',
        borderRadius: '2px',
        display: 'flex',
        justifyContent: 'center',
        alignItems: 'center'
      },
      {
        class: 'reply-button'
      }
    );
    this.replyButton.addEventListener('click', this.onOpenReply)
    this.replyButton.innerHTML = this.replySvgStr
    this.replyButton.style.left = (rect.left + rect.width - 65) + 'px'
    this.replyButton.style.top = (rect.top + rect.height + 8) + 'px'

    this.deletetButton = deletetButton
    this.outerLineContainer.append(rectContainer)
    this.outerLineContainer.append(deletetButton)
    this.outerLineContainer.append(this.replyButton)
  }

  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 });
    const actualBdWidth = 2

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

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

  handleClick () {
    if (!this.hidden || ['redaction', 'remove'].includes(this.layer.tool)) return
    this.hidden = false
    this.updateTool()
    const data = [this.markupContainer, this.outerLineContainer, this.deletetButton, this.replyButton]
    const toggleButton = document.querySelector('.toggle-button')
    toggleButton && data.push(toggleButton)
    onClickOutside(data, this.handleOutside.bind(this))
  }

  handleOutside () {
    this.hidden = !this.hidden
    if (this.layer.selectedElementName === this.annotation.name) {
      this.layer.selectedElementName = null
    }
    this.outerLineContainer.remove()
  }

  updateTool () {
    if (this.hidden) {
      if (this.layer.selectedElementName === this.annotation.name) {
        this.layer.selectedElementName = null
      }
      this.outerLineContainer.remove()
    } else {
      if (this.layer.selectedElementName !== this.annotation.name) {
        this.layer.selectedElementName = this.annotation.name
      }
      this.container.append(this.outerLineContainer)
    }
  }

  handleDelete (event) {
    if (this.layer.tool && event) {
      event.stopPropagation()
    }
    this.handleOutside()
    this.markupContainer.remove()
    this.annotation.isDelete = true
    const annotationData = {
      type: 'delete',
      annotation: {
        operate: "del-annot",
        name: this.annotation.name,
        pageIndex: this.page
      }
    }
    this.annotation.annotPtr && (annotationData.annotation.annotPtr = this.annotation.annotPtr)
    if (!event) {
      annotationData.type = 'empty'
    }
    this.eventBus.dispatch('annotationChange', annotationData)
  }

  setCss (ele, cssText) {
    if (!ele) return
    if (cssText) {
      for (let key in cssText) {
        ele.style[key] = cssText[key]
      }
    }
  }

  renderHighlight (positionArray) {
    const annotation = this.annotation
    const markupContainer = document.createElement('div')
    markupContainer.className = 'markup'
    for (let i = 0; i < positionArray.length; i++) {
      const currentPositionArray = positionArray[i]
      const container = document.createElement('div')
      this.setCss(container, {
        position: 'absolute',
        opacity: 0.5,
        top: currentPositionArray.top + 'px',
        left: currentPositionArray.left + 'px',
        width: currentPositionArray.width + 'px',
        height: currentPositionArray.height + 'px',
        backgroundColor: annotation.color
      })
      markupContainer.append(container)
    }
    this.container.append(markupContainer)
    this.markupContainer = markupContainer
  }

  renderUnderline (positionArray) {
    const annotation = this.annotation
    const markupContainer = document.createElement('div')
    markupContainer.className = 'markup'
    for (let i = 0; i < positionArray.length; i++) {
      const currentPositionArray = positionArray[i]
      const container = document.createElement('div')
      this.setCss(container, {
        position: 'absolute',
        mixBlendMode: 'multiply',
        opacity: annotation.opacity || 1,
        top: currentPositionArray.top + 'px',
        left: currentPositionArray.left + 'px',
        width: currentPositionArray.width + 'px',
        height: currentPositionArray.height + 'px',
        borderBottom: '2px solid ' + annotation.color
      })
      markupContainer.append(container)
    }
    this.container.append(markupContainer)
    this.markupContainer = markupContainer
  }

  renderSquiggly (positionArray) {
    const annotation = this.annotation
    const markupContainer = document.createElement('div')
    markupContainer.className = 'markup'
    for (let i = 0; i < positionArray.length; i++) {
      const currentPositionArray = positionArray[i]
      const container = document.createElement('div')
      this.setCss(container, {
        position: 'absolute',
        mixBlendMode: 'multiply',
        overflow: 'hidden',
        opacity: annotation.opacity || 1,
        top: currentPositionArray.top + 'px',
        left: currentPositionArray.left + 'px',
        width: currentPositionArray.width + 'px',
        height: currentPositionArray.height + 'px',
      })
      
      const squigglyBefore = document.createElement('div')
      this.setCss(squigglyBefore, {
        position: 'absolute',
        width: '100%',
        height: '5px',
        left: '0px',
        bottom: '1px',
        background: `radial-gradient(ellipse, transparent, transparent 8px, ${annotation.color} 9px, ${annotation.color} 10px, transparent 11px)`,
        backgroundSize: '22px 26px',
        backgroundRepeat: 'repeat-x'
      })
      const squigglyAfter = document.createElement('div')
      this.setCss(squigglyAfter, {
        position: 'absolute',
        width: '100%',
        height: '5px',
        left: '11px',
        bottom: '-2px',
        background: `radial-gradient(ellipse, transparent, transparent 8px, ${annotation.color} 9px, ${annotation.color} 10px, transparent 11px)`,
        backgroundSize: '22px 26px',
        backgroundPosition: '0px -22px',
        backgroundRepeat: 'repeat-x'
      })
      container.append(squigglyBefore)
      container.append(squigglyAfter)
      markupContainer.append(container)
    }
    this.container.append(markupContainer)
    this.markupContainer = markupContainer
  }

  renderStrikeout (positionArray) {
    const annotation = this.annotation
    const markupContainer = document.createElement('div')
    markupContainer.className = 'markup'
    for (let i = 0; i < positionArray.length; i++) {
      const currentPositionArray = positionArray[i]
      const container = document.createElement('div')
      this.setCss(container, {
        position: 'absolute',
        mixBlendMode: 'multiply',
        opacity: annotation.opacity || 1,
        top: currentPositionArray.top + 'px',
        left: currentPositionArray.left + 'px',
        width: currentPositionArray.width + 'px',
        height: currentPositionArray.height + 'px'
      })
      const strikeout = document.createElement('div')
      strikeout.classList.add('strikeout')
      this.setCss(strikeout, {
        position: 'absolute',
        opacity: 0.8,
        left: 0,
        width: '100%',
        height: '2px',
        transform: 'translateY(-50%)',
        backgroundColor: annotation.color
      })
      container.append(strikeout)
      markupContainer.append(container)
    }
    this.container.append(markupContainer)
    this.markupContainer = markupContainer
  }
  
  openReply () {
    this.eventBus.dispatch('openAnnotationReply', this.annotation)
  }
}

export default TextAnnotation
