<script lang="jsx">
import { debounce } from '../../utils'
import Codemirror from './codemirror'

export default {
  name: 'DgCodemirror',

  props: {
    value: {
      type: String,
      default: '',
    },
    mode: {
      type: [String, Object],
      default: () => ({ name: 'javascript', json: true }),
    },
    readonly: {
      type: Boolean,
      default: false,
    },
    autoResize: {
      type: Boolean,
      default: true,
    },
    tools: {
      type: String,
      default: '',
    },
    jsonLint: {
      type: Boolean,
      default: false,
    },
  },
  data: () => ({
    isFullscreen: false,
  }),
  watch: {
    value(val) {
      const cur = this.editor.getValue()

      if (cur !== val) {
        this.editor.setValue(val)
      }
    },
    mode(val) {
      this.editor.setOption('mode', val)
    },
  },
  mounted() {
    const editor = new Codemirror(this.$refs.el, {
      value: this.value,
      mode: this.mode,
      readOnly: this.readonly,
      tabSize: 2,
      lineWrapping: true,
      lineNumbers: true,
      autoCloseBrackets: true,
      autoCloseTags: true,
      foldGutter: true,
      lint: this.jsonLint,
      gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'],
      extraKeys: {
        Esc: () => {
          if (this.isFullscreen) this.isFullscreen = false
        },
      },
    })

    editor.on('change', () => {
      this.$emit('input', editor.getValue())
    })

    setTimeout(() => {
      editor.refresh()
    }, 50)

    if (this.autoResize) {
      const handler = debounce(() => editor.refresh())
      window.addEventListener('resize', handler)

      this.$once('hook:beforeDestroy', () => {
        window.removeEventListener('resize', handler)
      })
    }

    this.editor = editor
  },
  methods: {
    toggleFullscreen() {
      this.isFullscreen = !this.isFullscreen
    },
    format() {
      if (!(this.mode === 'json' || this.mode.json)) return

      try {
        this.$emit('input', JSON.stringify(JSON.parse(this.value), null, 2))
      } catch (e) {
        //
      }
    },
  },

  render() {
    const { isFullscreen, tools } = this
    const template = (
      <div class={['dg-codemirror', isFullscreen && 'dg-codemirror--fullscreen']}>
        <div ref="el" class="dg-codemirror__core"></div>
      </div>
    )

    const TEMPLATE_TOOLS = {
      fullscreen: (
        <el-tooltip content={!isFullscreen ? '全屏' : '取消全屏'}>
          <el-button
            icon={isFullscreen ? 'el-icon-bottom-left' : 'el-icon-top-right'}
            onClick={this.toggleFullscreen}
            type="primary"
            plain
            class="dg-codemirror__tool-btn"
          ></el-button>
        </el-tooltip>
      ),
      format: (
        <el-tooltip content="格式化" effect="dark">
          <el-button type="primary" plain class="dg-codemirror__tool-btn" onClick={this.format}>
            <span class="icon-text">ƒ</span>
          </el-button>
        </el-tooltip>
      ),
      slot: <slot>{this.$slots.default ? this.$slots.default : ''}</slot>,
    }

    const toolComps = tools
      .split(',')
      .map((i) => TEMPLATE_TOOLS[i.trim()])
      .filter(Boolean)

    if (toolComps.length) {
      const toolsWrapper = <div class="dg-codemirror__tools"></div>
      toolsWrapper.children = toolsWrapper.children || []
      toolsWrapper.children.push(...toolComps)
      template.children.unshift(toolsWrapper)
    }

    return template
  },
}
</script>
