import './index.scss'
import 'quill/dist/quill.core.css' // 核心样式
import 'quill/dist/quill.snow.css' // 有工具栏
import 'quill/dist/quill.bubble.css' // 无工具栏
import './font.css'
import React, { useState, useRef, useEffect } from 'react'
import Quill from 'quill'
import katex from 'katex'

import { fetchUploadImage } from '../../services/ojService.js'
import { getImageUrl } from 'educoder'
import ImageBlot from './ImageBlot'
import FillBlot from './FillBlot'
import LinkBlot from './link-blot'
import mediator from '../mediator'
import { defaultQuillOpt } from '../components/custom-editor'

let Size = Quill.import('attributors/style/size')
Size.whitelist = ['14px', '16px', '18px', '20px', false]
let fonts = ['Microsoft-YaHei', 'SimSun', 'SimHei', 'KaiTi', 'FangSong']
let Font = Quill.import('formats/font')

Font.whitelist = fonts; //将字体加入到白名单
window.Quill = Quill;
window.katex = katex;
Quill.register(ImageBlot);
Quill.register(Size);
Quill.register(LinkBlot);
Quill.register(Font, true);

Quill.register(FillBlot)

const FillStr = '▁'
const FillReg = new RegExp(FillStr, 'g')
const BRSTR = '<p><br></p>'

//hack 
function quillSetValue(el, value) {
  if (value && value.hasOwnProperty('ops')) {
    el.setContents(value)
  } else {
    if (value) {
      let rs = value
      if (rs.endsWith(BRSTR)) {
        rs += BRSTR
      }
      el.clipboard.dangerouslyPasteHTML(rs);
    }
  }
}

const BUTTONTIP = {
  'bold': '加粗',
  'strike': '删除线',
  'italic': '斜体',
  'underline': '下划线',
  'ordered': '有序列表',
  'bullet': '无序列表',
  'color': '字体颜色',
  'background': '背景色',
  'sub': '下标',
  'super': '上标',
  'image': '上传图片',
  'code-block': '代码块',
  'formula': '公式',
  'clean': '清除格式',
  'fill': '插入填空项',
  'align': '对齐',
  'header1': '标题一',
  'header2': '标题二',
  'header3': '标题三',
  'header4': '标题四',
  'header5': '标题五',
  'header6': '标题六'
}
function insertAfter(newNode, referenceNode) {
  referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
}

function initButtonTip(el) {
  const container = el.getModule('toolbar').container
  const btns = container.querySelectorAll('.ql-formats > button,.ql-formats>span')
  Array.from(btns).forEach(btn => {
    let value = btn.getAttribute('value')
    let cls = btn.classList[0].replace('ql-', '')
    btn.setAttribute('title', BUTTONTIP[value || cls] || BUTTONTIP[`${cls}${value}`])
    if (cls === 'fill') {
      let span = document.createElement('span')
      span.setAttribute('class', 'fill-tip')
      span.innerText = '点击插入填空项'
      span.addEventListener('click', () => { btn.click() })
      insertAfter(span, btn)
    }
  })
}
export default ({
  defaultValue,
  placeholder,
  readOnly,
  autoFocus = false,
  options,
  value,
  imgAttrs = {}, // 指定图片的宽高
  style = {},
  wrapStyle = {},
  showUploadImage,
  onContentChange,
  className,
  onAddFill,
  onDeleteFill
}) => {

  const editorRef = useRef(null)
  // quill 实例
  const [quill, setQuill] = useState(null)

  const bindings = {
    backspace: {
      key: 'Backspace',
      /**
       * @param {*} range
       *  { index, // 删除元素的位置
       *    length // 删除元素的个数, 当删除一个时， length=0， 其它等于删除的元素的个数
       *  }
       * @param {*} context 上下文
       */
      handler: function (range, context) {
        const [index, delArrs] = getFillInfo(range, this.quill)
        if (delArrs) {
          if (window.confirm('确定要删除这个填空吗?')) {
            onDeleteFill && onDeleteFill(index, delArrs.length) // 调用删除回调, 返回删除的元素下标[]
            return true
          } else {
            return false
          }
        }
        return true
      }
    }
  }
  const quillOption = {
    modules: {
      toolbar: options || defaultQuillOpt,
      'syntax': false,
      keyboard: {
        bindings: bindings
      }
    },
    readOnly,
    placeholder,
    theme: readOnly ? 'bubble' : 'snow',
  }

  //返回当前选中文件之前填空的索引，和选中的文本内有多少个填空
  function getFillInfo(range, quill) {
    const { index, length } = range
    const start = length === 0 ? index - 1 : index
    const selectionText = quill.getText(start, Math.max(1, length))
    const beforeSelectionText = quill.getText(0, start)
    return [(beforeSelectionText.match(FillReg) || []).length, selectionText.match(FillReg)]
  }

  useEffect(() => {
    const quillInstance = new Quill(editorRef.current, quillOption)
    setQuill(quillInstance)
    // 处理图片上传功能
    quillInstance.getModule('toolbar').addHandler('image', (e) => {
      const input = document.createElement('input')
      input.setAttribute('type', 'file')
      input.setAttribute('accept', 'image/*')
      input.click()
      input.onchange = async (e) => {
        const file = input.files[0] // 获取文件信息
        const formData = new FormData()
        formData.append('file', file)

        const range = quillInstance.getSelection(true)
        let fileUrl = '' // 保存上传成功后图片的url

        const result = await fetchUploadImage(formData)
        // 获取上传图片的url
        if (result.data && result.data.id) {
          fileUrl = getImageUrl(`api/attachments/${result.data.id}`)
        }
        const { width, height } = imgAttrs
        if (fileUrl) {
          let imgOption = {
            url: fileUrl,
            alt: '图片信息',
            width,
            height
          }
          quillInstance.insertEmbed(range.index, 'image', imgOption)
        }
      }
    })
    quillInstance.getModule('toolbar').addHandler('fill', (e) => {
      const range = quillInstance.getSelection(true)
      const [fillIndex, _] = getFillInfo(range, quillInstance)
      quillInstance.insertEmbed(range.index, 'fill', { "data-index": fillIndex, text: FillStr })
      quillInstance.setSelection(quillInstance.getLength(), 0, 'api')
      onAddFill && onAddFill(fillIndex) // 调用添加回调
    })

    initButtonTip(quillInstance)

    quillSetValue(quillInstance, value)

    if (autoFocus) {
      quillInstance.focus()
    }

    function onPreview(url) {
      if (showUploadImage) {
        showUploadImage(url)
      }
    }

    let unsub = mediator.subscribe('on-preview-image', onPreview)
    return () => {
      unsub()
    }
  }, [])

  useEffect(() => {
    if (quill) {
      if (readOnly === true) {
        quill.enable(false)
      } else {
        quill.enable(true)
      }
    }
  }, [quill, readOnly])

  useEffect(() => {
    quillSetValue(quill, defaultValue)
  }, [quill, defaultValue])

  useEffect(() => {
    if (quill) {
      quill.root.dataset.placeholder = placeholder;
    }
  }, [quill, placeholder])

  useEffect(() => {
    if (quill) {
      autoFocus ? quill.focus() : quill.blur()
    }
  }, [quill, autoFocus])

  useEffect(() => {
    if (quill && onContentChange) {
      function onChangeHandler(delta, oldDelta, source) {
        let html = editorRef.current.children[0].innerHTML
        let text = quill.getText()
        if (html === '<p><br></p>') html = ''
        if (onContentChange) {
          onContentChange(quill.getContents(), html, { quill, text, delta, oldDelta, source })
        }
      }
      quill.on('text-change', onChangeHandler)
      return () => {
        quill.off('text-change', onChangeHandler)
      }
    }
  }, [quill, onContentChange])

  // 返回结果
  return (
    <div className={`quill_editor_for_react_area ${className} `} style={wrapStyle}>
      <div ref={editorRef} style={style}></div>
    </div>
  )
}