<template>
    <div class="cm-container" :class="readonly?'readonly':'edit'" :id="id" :style="readonly?{height:'auto'}:{}">
        <codemirror
            ref="codemirror"
            v-model="content"
            :class="classMap"
            :options="options"
            @change="change"
        ></codemirror>
    </div>
</template>

<script>
import codemirrorlite from 'vue-codemirror-lite'
let codemirror = codemirrorlite.codemirror;

// 核心样式
// import 'codemirror/lib/codemirror.css'

// 引入主题后还需要在 options 中指定主题才会生效
import 'codemirror/theme/idea.css'
// 需要引入具体的语法高亮库才会有对应的语法高亮效果
// codemirror 官方其实支持通过 /addon/mode/loadmode.js 和 /mode/meta.js 来实现动态加载对应语法高亮库
// 但 vue 貌似没有无法在实例初始化后再动态加载对应 JS ，所以此处才把对应的 JS 提前引入
import 'codemirror/mode/javascript/javascript.js';
import 'codemirror/mode/htmlmixed/htmlmixed.js';
import 'codemirror/mode/css/css.js';
// import 'codemirror/mode/xml/xml.js';
// import 'codemirror/mode/shell/shell.js';
// import 'codemirror/mode/sql/sql.js';
//代码补全提示
import 'codemirror/addon/hint/anyword-hint.js';
import 'codemirror/addon/hint/css-hint.js';
import 'codemirror/addon/hint/html-hint.js';
import 'codemirror/addon/hint/javascript-hint.js';
import 'codemirror/addon/hint/show-hint.css';
import 'codemirror/addon/hint/show-hint.js';
import 'codemirror/addon/hint/sql-hint.js';
import 'codemirror/addon/hint/xml-hint.js';

import'codemirror/addon/fold/foldgutter.css'
import 'codemirror/addon/fold/foldcode.js'
import 'codemirror/addon/fold/brace-fold.js'

import 'codemirror/addon/edit/closebrackets.js'

import 'codemirror/addon/display/fullscreen.css'
import StringUtil from "../../../util/pattern/string"
import DomUtil from "../../../util/pattern/dom"
import * as codeUtil from "../../../util/develop/code"
//https://blog.csdn.net/lyd135364/article/details/50827648
export default {
    name: "CodeJs",
    components: {codemirror},
    props: {
        value: {
            type: String
        },
        /*代码模式*/
        mode: {
            type: String,
            default: "js" // "html"
        },
        /*是否允许拖动改变大小*/
        resize: {
            type: Boolean,
            default: true
        },
        /*高度*/
        height: {
            type: Number,
            default: 0
        },
        /*是否禁止编辑*/
        readonly: {
            type: Boolean,
            default: false
        }
    },
    data() {
        return {
            style:DomUtil.getStyle(),
            id: StringUtil.randomString("id"),
            isFullScreen:false,
            content: "",
            classMap: {"CodeMirror-fullscreen": false},
            options: {},
            item: {}
        };
    },
    model: {
        prop: 'value',
        event: 'change'
    },
    created() {
        let vm = this;
        this.options = {
            mode: {'js': 'javascript', 'javascript': 'javascript', 'html': 'htmlmixed'}[vm.mode],
            // 缩进格式
            tabSize: 4,
            // 主题，对应主题库 JS 需要提前引入
            // theme: 'idea',
            indentUnit: 4,         // 缩进单位为4
            styleActiveLine: true, // 当前行背景高亮
            // 显示行号
            lineNumbers: true,
            lineWrapping: true,//在长行时文字是换行(wrap)还是滚动(scroll)，默认为滚动(scroll)。
            fullScreen: true,
            extraKeys: {//全屏
                'Ctrl-Space': 'autocomplete',
                // "Ctrl-Shift-F": function autoFormat(editor) {debugger
                //     // var totalLines = editor.lineCount();
                //     // editor.autoFormatRange({line:0, ch:0}, {line:totalLines});
                //     this.content=beautify[this.mode](this.content, { indent_size: 4, space_in_empty_paren: true });
                // },//代码格式化
                "F11": function (cm) {
                    vm.toggleFullScreen();
                    // cm.setOption("fullScreen", !cm.getOption("fullScreen"));
                },
                "Esc": function (cm) {
                    vm.toggleFullScreen();
                    // vm.classMap["CodeMirror-fullscreen"]=false;
                    // if (cm.getOption("fullScreen")) cm.setOption("fullScreen", false);
                }
            }
        };
        if (this.readonly) {
            this.options.readOnly = 'nocursor';
        }  //readOnly:'nocursor',
        this.initStyleInnerHtml();
        this.setValue();
    },
    computed: {
        // get current editor object
        // return this.$refs.codemirror.editor
        styleHtml() {
        }
    },
    methods: {
        toggleFullScreen(){
            let CodeMirror=$(this.$refs.codemirror.$el).find('.CodeMirror');
            if(this.isFullScreen){
                this.isFullScreen=false;
                DomUtil.setStyle(this.style,this.styleInnerHtml);
                this.CodeMirrorStyle && CodeMirror.attr("style",this.CodeMirrorStyle);
                CodeMirror.removeClass("CodeMirror-fullscreen");
            }else{
                this.isFullScreen=true;
                DomUtil.setStyle(this.style,"");
                this.CodeMirrorStyle= CodeMirror.attr("style");
                CodeMirror.attr("style","");
                CodeMirror.addClass("CodeMirror-fullscreen")
            }
        },
        initStyleInnerHtml(){
            let styleInnerHtml="";
            if(this.height>0){
                let max=Math.min(this.height,300);
                let h_=`${this.height}px`;
                styleInnerHtml= `
                   #${this.id} .CodeMirror{
                        resize: ${this.resize?'both':'none'};
                        min-height: ${max}px;
                        height: ${h_};
                        min-width: ${max}px;
                        max-width: 100%;
                   }
                `
            }else{
                styleInnerHtml= `
                   #${this.id} .CodeMirror{
                        resize: ${this.resize?'both':'none'};
                        min-height: 300px;
                        min-width: 300px;
                        max-width: 100%;
                   }
                `
            }
            DomUtil.setStyle(this.style,styleInnerHtml);
            this.styleInnerHtml=styleInnerHtml;
        },
        getModeBeautify() {
            let b = codeUtil;
            switch (this.mode) {
                case "js":
                case "javascript":
                    b = codeUtil.getBeautifyJavascriptCode;
                    break;
                case "html":
                    b = codeUtil.getBeautifyHtmlCode;
                    break;
                case "css":
                    b = codeUtil.getBeautifyCssCode;
                    break;

            }
            return b;
        },
        setValue(value = this.value || "") {
            this.content = this.getModeBeautify()(value);
        },
        change: function (code) {
            let vm = this;
            if (vm.changeDataTimer) {
                clearTimeout(this.changeDataTimer);
                vm.changeDataTimer = null;
            }
            vm.changeDataTimer = setTimeout(function () {
                vm.changeDataTimer = null;
                vm.$emit('change', code);
            }, 300)
        }
    }
}
</script>

<style scoped lang="less">
.cm-container {
    font-size: 12px;
    line-height: 150%;
}
.edit{
    /deep/ .CodeMirror {
        border: #ddd solid 1px;
        //min-height: 300px;
        //min-width: 300px;
    }
}
.readonly{
    /deep/ .CodeMirror {
        border: #ddd solid 1px;
    }
}
</style>
