<!-- @author Kyles Light -->
<!-- @email kuilin@yangqianguan.com -->
<!-- @date 2018-03-28 15:20:38.000 -->
<!-- @desc generated by yqg-cli@0.0.18 -->

<template>
    <div class="yqg-code-textarea">
        <codemirror
            ref="cm"
            :value="value"
            :options="CodeMirrorOptions"
            v-on="$listeners"
        />
        <a-button
            v-if="reformatJson"
            style="margin-top: 10px;"
            @click="reformatJSON()"
        >
            Reformat JSON
        </a-button>
    </div>
</template>

<script type="text/babel">

import {codemirror} from 'vue-codemirror';

import {pureJSONString, reformatJson} from '../../../util/json';

import 'codemirror/mode/clike/clike';
import 'codemirror/mode/groovy/groovy';
import 'codemirror/mode/javascript/javascript';
import 'codemirror/mode/sql/sql';
import 'codemirror/mode/yaml/yaml';
import 'codemirror/lib/codemirror.css';
import 'codemirror/theme/neo.css';
import 'codemirror/addon/hint/show-hint.css';
import 'codemirror/addon/display/placeholder';

import 'codemirror/addon/edit/closebrackets';
import 'codemirror/addon/edit/closetag';
import 'codemirror/addon/edit/matchbrackets';
import 'codemirror/addon/edit/matchtags';
import 'codemirror/addon/hint/show-hint';
import 'codemirror/addon/hint/sql-hint';
import 'codemirror/addon/fold/foldgutter.css';
import 'codemirror/addon/fold/foldcode';
import 'codemirror/addon/fold/foldgutter';
import 'codemirror/addon/fold/brace-fold';
import 'codemirror/addon/fold/comment-fold';
import 'codemirror/addon/fold/indent-fold';

const CodeMirrorOptions = {
    // Configuration
    indentUnit: 4,
    smartIndent: false, // TODO by panezhang use JSON-LD mode and enable smartIndent
    tabSize: 4,
    lineWrapping: true,

    // Addon Configuration
    autoCloseBrackets: true,
    autoCloseTags: true,
    matchBrackets: true,
    matchTags: true,

    extraKeys: {
        'Tab': cm => {
            if (cm.somethingSelected()) {
                cm.indentSelection('add');

                return;
            }

            if (cm.getOption('indentWithTabs')) {
                cm.replaceSelection('\t', 'end', '+input');
            } else {
                cm.execCommand('insertSoftTab');
            }
        },

        'Shift-Tab': cm => {
            cm.indentSelection('subtract');
        }

        // TODO by panezhang reformat
        // 'Alt-Cmd-L': () => {
        //
        // }
    }
};

export default {
    name: 'YqgCodeTextarea',

    components: {
        codemirror
    },

    props: {
        value: {
            type: String,
            required: true
        },

        mode: {
            type: String,
            default: 'text/javascript'
        },

        disabled: {
            type: Boolean,
            default: false
        },

        options: {
            type: Object,
            default: () => ({})
        },
        // Reformat JSON的按钮
        reformatJson: {
            type: Boolean,
            default: false
        }
    },

    computed: {
        CodeMirrorOptions() {
            const {options, mode, disabled} = this;

            return {
                ...CodeMirrorOptions,
                mode,
                ...options,
                ...disabled ? {
                    // disabled: 禁止输入、隐藏光标、可以复制
                    // ref: https://github.com/codemirror/CodeMirror/issues/2568
                    readOnly: true,
                    cursorBlinkRate: -1
                } : {}
            };
        },

        codeMirror() {
            return this.$refs.cm.codemirror;
        }
    },

    mounted() {
        if (this.CodeMirrorOptions.enableAutocomplete) {
            this.codeMirror.on('change', (editor, {origin, text}) => {
                if (origin === '+input' && text.length === 1 && text[0].trim()) {
                    editor.showHint({
                        completeSingle: false
                    });
                }
            });
        }
    },

    methods: {
        reformatJSON() {
            const {value} = this;
            try {
                pureJSONString(value);
                this.$emit('input', reformatJson(value, this));
            } catch (error) {
                // ignore
            }
        }
    }
};

</script>

<style lang="scss" rel="stylesheet/scss" src="./index.scss" />
