<!--
 * @Author: WangJiaCheng
 * @Date: 2021-07-28 14:18:16
 * @LastEditors: WangJiaCheng
 * @LastEditTime: 2021-07-29 16:37:04
 * @Description: 代码编辑
-->
<template>
  <div style="height:100%">
    <el-row style="height:100%;overflow:auto">
      <el-col :md="24" :lg="12" class="left-editor">
        <el-tabs v-model="activeTab" type="card" class="editor-tabs">
          <el-tab-pane name="html">
            <span slot="label">
              <i v-if="activeTab==='html'" class="el-icon-edit" />
              <i v-else class="el-icon-document" />
              template
            </span>
          </el-tab-pane>
          <el-tab-pane name="js">
            <span slot="label">
              <i v-if="activeTab==='js'" class="el-icon-edit" />
              <i v-else class="el-icon-document" />
              script
            </span>
          </el-tab-pane>
          <el-tab-pane name="css">
            <span slot="label">
              <i v-if="activeTab==='css'" class="el-icon-edit" />
              <i v-else class="el-icon-document" />
              css
            </span>
          </el-tab-pane>
        </el-tabs>
        <div v-show="activeTab==='html'" id="codeEditorHtml" class="tab-editor" />
        <div v-show="activeTab==='js'" id="codeEditorJs" class="tab-editor" />
        <div v-show="activeTab==='css'" id="codeEditorCss" class="tab-editor" />
      </el-col>
    </el-row>
  </div>
</template>

<script>
import { parse } from '@babel/parser'
import ClipboardJS from 'clipboard'
import { saveAs } from 'file-saver'
import {
  makeUpHtml, vueTemplate, vueScript, cssStyle, makeUpWcHtml
} from '@/components/generator/html'
import { makeUpJs, makeUpWcJs } from '@/components/generator/js'
import { buildTable, makeTableJs } from '@/components/generator/table'
import { buildTabs, makeTabsJs } from '@/components/generator/tabs'
import { makeUpCss } from '@/components/generator/css'
import { exportDefault, beautifierConf } from '@/utils/index'
import loadMonaco from '@/utils/loadMonaco'
import loadBeautifier from '@/utils/loadBeautifier'

const editorObj = {
  html: null,
  js: null,
  css: null
}
const mode = {
  html: 'html',
  js: 'javascript',
  css: 'css'
}
let beautifier
let monaco

export default {
  name: 'CodeEditor',
  props: {
    codeType: {
      type: String,
      default: 'page'
    },
    formData: {
      type: Object,
      default() {
        return {}
      }
    },
    generateConf: {
      type: Object,
      default() {
        return {}
      }
    }
  },
  data() {
    return {
      activeTab: 'html',
      htmlCode: '',
      jsCode: '',
      cssCode: '',
      codeFrame: '',
      isIframeLoaded: false,
      isInitcode: false, // 保证open后两个异步只执行一次runcode
      isRefreshCode: false, // 每次打开都需要重新刷新代码
      scripts: [],
      links: [],
      monaco: null
    }
  },
  watch: {
    codeType: {
      handler(val) {
        if (val) {
          this.renderCode()
        }
      }
    }
  },
  mounted() {
    window.addEventListener('keydown', this.preventDefaultSave)
    const clipboard = new ClipboardJS('.copy-btn', {
      text: trigger => {
        const codeStr = this.generateCode()
        this.$notify({
          title: '成功',
          message: '代码已复制到剪切板，可粘贴。',
          type: 'success'
        })
        return codeStr
      }
    })
    clipboard.on('error', e => {
      this.$message.error('代码复制失败')
    })
  },
  beforeDestroy() {
    window.removeEventListener('keydown', this.preventDefaultSave)
  },
  methods: {
    setEditorValue(id, type, codeStr) {
      if (editorObj[type]) {
        editorObj[type].setValue(codeStr)
      } else {
        editorObj[type] = monaco.editor.create(document.getElementById(id), {
          value: codeStr,
          theme: 'vs-dark',
          language: mode[type],
          automaticLayout: true
        })
      }
      // ctrl + s 刷新
      editorObj[type].onKeyDown(e => {
        if (e.keyCode === 49 && (e.metaKey || e.ctrlKey)) {
          this.runCode()
        }
      })
    },
    renderCode() {
      const { type = 'file' } = this.generateConf
      if (this.codeType === 'page') {
        this.htmlCode = makeUpWcHtml(this.formData, type)
        this.jsCode = makeUpWcJs(this.formData, type)
        this.cssCode = makeUpCss(this.formData)
      }
      if (this.codeType === 'tab') {
        this.htmlCode = buildTabs(this.formData, type)
        this.jsCode = makeTabsJs(this.formData, type)
        this.cssCode = makeUpCss(this.formData)
      }
      if (this.codeType === 'list') {
        this.htmlCode = buildTable(this.formData, type)
        this.jsCode = makeTableJs(this.formData, type)
        this.cssCode = makeUpCss(this.formData)
      }
      if (this.codeType === 'form') {
        this.htmlCode = makeUpHtml(this.formData.formModel, type)
        this.jsCode = makeUpJs(this.formData.formModel, type)
        this.cssCode = makeUpCss(this.formData.formModel)
      }

      loadBeautifier(btf => {
        beautifier = btf
        this.htmlCode = beautifier.html(this.htmlCode, beautifierConf.html)
        this.jsCode = beautifier.js(this.jsCode, beautifierConf.js)
        // this.cssCode = beautifier.css(this.cssCode, beautifierConf.html)

        loadMonaco(val => {
          monaco = val
          this.setEditorValue('codeEditorHtml', 'html', this.htmlCode)
          this.setEditorValue('codeEditorJs', 'js', this.jsCode)
          this.setEditorValue('codeEditorCss', 'css', this.cssCode)
        })
      })
    }
  }
}
</script>

<style lang="less" scoped>
@import '@/styles/mixin.scss';
.tab-editor {
  position: absolute;
  top: 33px;
  bottom: 0;
  left: 0;
  right: 0;
  font-size: 14px;
}
.left-editor {
  position: relative;
  height: 500px;
  background: #1e1e1e;
  overflow: hidden;
  width: 100%;
}
.setting{
  position: absolute;
  right: 15px;
  top: 3px;
  color: #a9f122;
  font-size: 18px;
  cursor: pointer;
  z-index: 1;
}
.right-preview {
  height: 100%;
  .result-wrapper {
    height: calc(100vh - 33px);
    width: 100%;
    overflow: auto;
    padding: 12px;
    box-sizing: border-box;
  }
}
</style>
