import { html, LitElement, PropertyDeclarations } from 'lit'

export default class CodeInput extends LitElement {
  static get tagName() {
    return 'btu-code-input'
  }

  static get properties(): PropertyDeclarations {
    return {
      name: {},
      type: {},
      placeholder: {},
      placeholderEditable: { type: Boolean },
      value: {},
    }
  }

  name?: string
  type?: string
  placeholder?: string
  placeholderEditable?: boolean
  #editor?: CodeMirror.Editor
  #value?: string

  get value() {
    if (this.#editor) {
      return this.#editor.getValue()
    } else {
      return this.#value || ''
    }
  }

  set value(value) {
    if (this.#editor) {
      this.#editor.setValue(value || '')
    } else {
      this.#value = value
    }
  }

  createRenderRoot() {
    return this
  }

  render() {
    return this.name
      ? html`<input type="hidden" name="${this.name}" .value=${this.value} />`
      : ''
  }

  async firstUpdated() {
    const { default: CodeMirror } = await import(
      /* webpackChunkName: 'CodeMirror' */ './CodeMirror'
    )

    this.#editor = CodeMirror(this, {
      indentUnit: 4,
      inputStyle: 'contenteditable',
      lineNumbers: true,
      lineWrapping: true,
      mode: this.type || '',
      placeholder: this.placeholder || '',
      value: this.value || '',
    })

    this.#editor.on('change', () => {
      this.requestUpdate()
      this.dispatchEvent(new Event('change', { bubbles: true }))
    })

    if (this.placeholderEditable) {
      this.#editor.on('focus', () => {
        if (this.#editor && !this.#editor.getValue()) {
          this.#editor.setValue(this.placeholder || '')
        }
      })

      this.#editor.on('blur', () => {
        if (this.#editor && this.#editor.getValue() === this.placeholder) {
          this.#editor.setValue('')
        }
      })
    }
  }
}

customElements.define(CodeInput.tagName, CodeInput)
