import React, { useEffect, useRef, useMemo } from 'react'
import 'katex/dist/katex.min.css'
import marked, { getTocContent, cleanToc, getMathExpressions, resetMathExpressions } from '../common/marked';
import 'code-prettify'
import dompurify from 'dompurify';

import { renderToString } from 'katex'

const preRegex = /<pre[^>]*>/g
function _unescape(str) {
  let div = document.createElement('div')
  div.innerHTML = str
  return div.childNodes.length === 0 ? "" : div.childNodes[0].nodeValue
}



export default ({
  value = '',
  className,
  style = {},
  url
}) => {
  let str = String(value);
  const html = useMemo(() => {
    let rs = marked(str);
    const math_expressions = getMathExpressions();
    if (str.match(/\[TOC\]/)) {
      rs = rs.replace("<p>[TOC]</p>", getTocContent())
      cleanToc()
    }
    rs = rs.replace(/(__special_katext_id_\d+__)/g, (_match, capture) => {
      const { type, expression } = math_expressions[capture]
      return renderToString(_unescape(expression) || '', { displayMode: type === 'block', throwOnError: false, output: 'html' })
    })
    rs = rs.replace(/▁/g, "▁▁▁")
    resetMathExpressions()
    return dompurify.sanitize(rs)
  }, [str]);

  // 锚点跳转，链接地址里含#对应的id
  useEffect(()=>{
    if(url && url.hash && html){
      let u = url.hash;
      if(u){
        let id = decodeURIComponent(u.split("#")[1]);
        let ele = document.getElementById(id);
        if(ele){
          window.scrollTo(0, ele.offsetTop + 120);
        }
      }
    }
  },[url,html])

  const el = useRef();
  function onAncherHandler(e) {
    let target = e.target;
    if (target.tagName.toUpperCase() === 'A') {
      let ancher = target.getAttribute('href');
      if (ancher && ancher.startsWith('#')) {
        e.preventDefault()
        let viewEl = document.getElementById(ancher.replace('#', ''))
        if (viewEl) {
          viewEl.scrollIntoView(true)
        }
      }
    }
  }

  useEffect(() => {
    if (el.current && html) {
      if (html.match(preRegex)) {
        window.PR.prettyPrint()
      }
    }
    if (el.current) {
      el.current.addEventListener('click', onAncherHandler)
      return () => {
        el.current.removeEventListener('click', onAncherHandler)
        resetMathExpressions()
        cleanToc()
      }
    }
  }, [html, el.current, onAncherHandler])
  return (
    <div
      ref={el}
      style={style}
      className={`${className ? className : ''} markdown-body`}
      dangerouslySetInnerHTML={{ __html: html }}
    ></div>
  )
}
