import { reactive, markRaw, Component } from 'vue'
import { AnyObject } from '@tiptap/core'
import { Editor } from './Editor'

export interface VueRendererOptions {
  editor: Editor,
  props?: AnyObject,
}

export class VueRenderer {
  id: string

  editor: Editor

  component: Component

  teleportElement: Element

  element: Element

  props: AnyObject

  constructor(component: Component, { props = {}, editor }: VueRendererOptions) {
    this.id = Math.floor(Math.random() * 0xFFFFFFFF).toString()
    this.editor = editor
    this.component = markRaw(component)
    this.teleportElement = document.createElement('div')
    this.element = this.teleportElement
    this.props = reactive(props)
    this.editor.vueRenderers.set(this.id, this)

    if (this.editor.contentComponent) {
      this.editor.contentComponent.update()

      if (this.teleportElement.children.length !== 1) {
        throw Error('VueRenderer doesn’t support multiple child elements.')
      }

      this.element = this.teleportElement.firstElementChild as Element
    }
  }

  get ref(): any {
    return this.editor.contentComponent?.ctx.$refs[this.id]
  }

  updateProps(props: AnyObject = {}): void {
    Object
      .entries(props)
      .forEach(([key, value]) => {
        this.props[key] = value
      })
  }

  destroy(): void {
    this.editor.vueRenderers.delete(this.id)
  }
}
