import { defineComponent, nextTick, onMounted, reactive, ref, defineExpose } from 'vue'
import { basicSetup } from 'codemirror'
import { EditorView } from '@codemirror/view'
import { EditorState, StateEffect } from '@codemirror/state'
import { javascript } from '@codemirror/lang-javascript'
import { sql } from '@codemirror/lang-sql'
import { useId } from '@/hooks'

export const CodeMirrorTsx = defineComponent({
  name: 'code-mirror-tsx',
  props: {
    bodyType: {
      type: String,
      default: 'javascript' //  javascript json
    },
    bodyJson: {
      type: String,
      default: ''
    },
    numberOfRows: {
      type: Number,
      default: 6
    }
  },
  setup (props, ctx) {
    const id = useId()

    const state = reactive({})

    const editorRef = ref()

    const view = ref<EditorView>()

    const transDoc = () => {
      if (props.numberOfRows && !props.bodyJson) {
        return new Array(props.numberOfRows).fill(0).map(item => '\n').join('')
      }
      return props.bodyType === 'javascript' ? props.bodyJson : JSON.stringify(JSON.parse(props.bodyJson), null, '\t')
    }

    const createView = () => {
      const extensions = [basicSetup]
      if (props.bodyType === 'javascript') {
        extensions.push(javascript())
      } else if (props.bodyType === 'sql') {
        extensions.push(sql())
      }
      const editorState = EditorState.create({
        doc: transDoc(),
        extensions: extensions
      })

      view.value = new EditorView({
        state: editorState,
        parent: document.getElementById(`editorRef-${id}`)!
      })
    }

    onMounted(() => {
      nextTick(() => {
        setTimeout(() => {
          createView()
        }, 1000)
      })
    })

    ctx.expose({
      getValue: () => JSON.parse(JSON.stringify(view.value!.state.doc.toJSON().join('')))
    })

    return () => (
      <div ref="editorRef" id={`editorRef-${id}`}></div>
    )
  }
})
