import { Text } from '@svgdotjs/svg.js'
import {
  getStrWithBrFromHtml,
  focusInput,
  selectAllInput
} from '../../utils/index'

// 创建文字节点
function createText(data) {
  let g = this.associativeLineDraw.group()
  const setActive = () => {
    if (
      !this.activeLine ||
      this.activeLine[3] !== data.node ||
      this.activeLine[4] !== data.toNode
    ) {
      this.setActiveLine({
        ...data,
        text: g
      })
    }
  }
  g.click(e => {
    e.stopPropagation()
    setActive()
  })
  g.on('dblclick', e => {
    e.stopPropagation()
    setActive()
    if (!this.activeLine) return
    this.showEditTextBox(g)
  })
  return g
}

//  显示文本编辑框
function showEditTextBox(g) {
  this.mindMap.emit('before_show_text_edit')
  // 注册回车快捷键
  this.mindMap.keyCommand.addShortcut('Enter', () => {
    this.hideEditTextBox()
  })
  // 输入框元素没有创建过，则先创建
  if (!this.textEditNode) {
    this.textEditNode = document.createElement('div')
    this.textEditNode.className = 'associative-line-text-edit-warp'
    this.textEditNode.style.cssText = `position:fixed;box-sizing: border-box;background-color:#fff;box-shadow: 0 0 20px rgba(0,0,0,.5);padding: 3px 5px;margin-left: -5px;margin-top: -3px;outline: none; word-break: break-all;`
    this.textEditNode.setAttribute('contenteditable', true)
    this.textEditNode.addEventListener('keyup', e => {
      e.stopPropagation()
    })
    this.textEditNode.addEventListener('click', e => {
      e.stopPropagation()
    })
    const targetNode = this.mindMap.opt.customInnerElsAppendTo || document.body
    targetNode.appendChild(this.textEditNode)
  }
  let [, , , node, toNode] = this.activeLine
  let {
    associativeLineTextFontSize,
    associativeLineTextFontFamily,
    associativeLineTextLineHeight
  } = this.getStyleConfig(node, toNode)
  let { defaultAssociativeLineText, nodeTextEditZIndex } = this.mindMap.opt
  let scale = this.mindMap.view.scale
  let text = this.getText(node, toNode)
  let textLines = (text || defaultAssociativeLineText).split(/\n/gim)
  this.textEditNode.style.fontFamily = associativeLineTextFontFamily
  this.textEditNode.style.fontSize = associativeLineTextFontSize * scale + 'px'
  this.textEditNode.style.lineHeight =
    textLines.length > 1 ? associativeLineTextLineHeight : 'normal'
  this.textEditNode.style.zIndex = nodeTextEditZIndex
  this.textEditNode.innerHTML = textLines.join('<br>')
  this.textEditNode.style.display = 'block'
  this.updateTextEditBoxPos(g)
  this.showTextEdit = true
  // 如果是默认文本要全选输入框
  if (text === '' || text === defaultAssociativeLineText) {
    selectAllInput(this.textEditNode)
  } else {
    // 否则聚焦即可
    focusInput(this.textEditNode)
  }
}

// 删除文本编辑框元素
function removeTextEditEl() {
  if (!this.textEditNode) return
  const targetNode = this.mindMap.opt.customInnerElsAppendTo || document.body
  targetNode.removeChild(this.textEditNode)
}

// 处理画布缩放
function onScale() {
  this.hideEditTextBox()
}

// 更新文本编辑框位置
function updateTextEditBoxPos(g) {
  let rect = g.node.getBoundingClientRect()
  if (this.textEditNode) {
    this.textEditNode.style.minWidth = `${rect.width + 10}px`
    this.textEditNode.style.minHeight = `${rect.height + 6}px`
    this.textEditNode.style.left = `${rect.left}px`
    this.textEditNode.style.top = `${rect.top}px`
  }
}

//  隐藏文本编辑框
function hideEditTextBox() {
  if (!this.showTextEdit) {
    return
  }
  let [path, , text, node, toNode] = this.activeLine
  let str = getStrWithBrFromHtml(this.textEditNode.innerHTML)
  // 如果是默认文本，那么不保存
  let isDefaultText = str === this.mindMap.opt.defaultAssociativeLineText
  str = isDefaultText ? '' : str
  this.mindMap.execCommand('SET_NODE_DATA', node, {
    associativeLineText: {
      ...(node.getData('associativeLineText') || {}),
      [toNode.getData('uid')]: str
    }
  })
  this.textEditNode.style.display = 'none'
  this.textEditNode.innerHTML = ''
  this.showTextEdit = false
  this.renderText(str, path, text, node, toNode)
  this.mindMap.emit('hide_text_edit')
}

// 获取某根关联线的文字
function getText(node, toNode) {
  let obj = node.getData('associativeLineText')
  if (!obj) {
    return ''
  }
  return obj[toNode.getData('uid')] || ''
}

// 渲染关联线文字
function renderText(str, path, text, node, toNode) {
  if (!str) return
  let { associativeLineTextFontSize, associativeLineTextLineHeight } =
    this.getStyleConfig(node, toNode)
  text.clear()
  let textArr = str.replace(/\n$/g, '').split(/\n/gim)
  textArr.forEach((item, index) => {
    // 避免尾部的空行不占宽度，导致文本编辑框定位异常的问题
    if (item === '') {
      item = '﻿'
    }
    let textNode = new Text().text(item)
    textNode.y(
      associativeLineTextFontSize * associativeLineTextLineHeight * index
    )
    this.styleText(textNode, node, toNode)
    text.add(textNode)
  })
  updateTextPos(path, text)
}

// 给文本设置样式
function styleText(textNode, node, toNode) {
  let {
    associativeLineTextColor,
    associativeLineTextFontSize,
    associativeLineTextFontFamily
  } = this.getStyleConfig(node, toNode)
  textNode
    .fill({
      color: associativeLineTextColor
    })
    .css({
      'font-family': associativeLineTextFontFamily,
      'font-size': associativeLineTextFontSize + 'px'
    })
}

// 更新关联线文字位置
function updateTextPos(path, text) {
  let pathLength = path.length()
  let centerPoint = path.pointAt(pathLength / 2)
  let { width: textWidth, height: textHeight } = text.bbox()
  text.x(centerPoint.x - textWidth / 2)
  text.y(centerPoint.y - textHeight / 2)
}

export default {
  getText,
  createText,
  styleText,
  onScale,
  showEditTextBox,
  removeTextEditEl,
  hideEditTextBox,
  updateTextEditBoxPos,
  renderText,
  updateTextPos
}
