<template>
    <div class="flex flex-pack-center" style="height: 100%;height: 100%;margin-top: 5px;">
        <!--左侧面板-->
        <div class="dev-container dev-left-panel">
            <el-tabs value="default" :stretch="true">
                <el-tab-pane label="默认" name="default">
                    <el-collapse v-model="componentGroup">
                        <template v-for="devComponent in componentMenus">
                            <el-collapse-item :name="devComponent.title">
                                <template slot="title">
                                    <span class="dev-collapse-title">{{ devComponent.title }}</span>
                                </template>
                                <div class="dev-panel-item">
                                    <div
                                        v-for="item in devComponent.list"
                                        :key="item.type"
                                        class="dev-comp-item"
                                        :data-type="item.type"
                                        @click="clickItemEvent(item.type)"
                                    >
                                        <i :class="item.icon"/>&nbsp;{{ item.title }}
                                    </div>
                                </div>
                            </el-collapse-item>
                        </template>
                    </el-collapse>
                </el-tab-pane>
                <el-tab-pane label="自定义" name="custom"/>
            </el-tabs>
        </div>

        <!--中间面板-->
        <div class="flex-1 flex flex-direction-column" style="overflow: auto;">
            <ap-container>
                <ap-main margin="0101" style="overflow: auto;">
                    <div style="position: relative;float: right;">
                        <el-button-group>
                            <el-button icon="el-icon-copy" @click="copyCode($event)">复制</el-button>
                        </el-button-group>
                    </div>
                    <div class="dev-code" v-html="renderAbapCode">
                    </div>
                </ap-main>
            </ap-container>
        </div>

        <!--右侧面板-->
        <div class="dev-container dev-right-panel flex flex-direction-column">
            <div class="flex-1" style="overflow: auto;padding: 10px 5px;">
                <comment :is="currentItem" @dataChange="itemDataChange"/>
            </div>
        </div>
    </div>
</template>

<script>
import componentMenus from './componentMenus'
import abapKeywords from './abapKeywords'
import DynamicItem from "./DynamicItem";
import clipboard from 'ap-util/util/ClipboardUtil'

// 批量导入组件
const allComponents = require.context('./items', false, /\.vue$/)
const apDevComponentItems = {}
allComponents.keys().forEach(fileName => {
    const comp = allComponents(fileName)
    apDevComponentItems[fileName.replace(/^\.\/(.*)\.\w+$/, '$1')] = comp.default
})
apDevComponentItems['DynamicItem'] = DynamicItem

export default {
    name: 'CodePanel',
    components: apDevComponentItems,
    data() {
        return {
            componentMenus: componentMenus,
            componentGroup: [],
            currentItem: '',
            abapCode: '',
            renderAbapCode: '',
            renderMap: {},
        }
    },
    computed: {},
    created() {
        for (let i = 0; i < componentMenus.length; i++) {
            this.componentGroup.push(componentMenus[i].title)
        }
    },
    methods: {
        clickItemEvent(type) {
            this.currentItem = 'abap-code-' + type
        },
        // 子组件数据修改
        itemDataChange(abapCode) {
            this.abapCode = abapCode;
            this.renderAbapCode = this.renderCode(abapCode);
        },
        copyCode(event) {
            clipboard(this.abapCode, event)
        },
        getMap(str){
            this.renderIndex = this.renderIndex + 1;
            let key = "@" + this.renderIndex + "@";
            this.renderMap[key] = str;
            return key;
        },
        // 渲染代码式样
        renderCode(code) {
            this.renderMap = {};
            this.renderIndex = 0;
            // 注释：最优先
            code = this.renderNotes(code);
            // 字符串
            code = this.renderString(code);
            // 数值替换
            code = this.renderNumber(code);
            // 关键字渲染
            code = this.renderKeys(code);
            // 符号
            code = this.renderChars(code);
            code = this.replaceMap(code);
            this.renderAbapCode = code;
            return code;
        },
        replaceMap(code){
            let renderMap = this.renderMap;
            for (let key in renderMap) {
                if (!key.startsWith("@")) {
                    continue;
                }
                code = code.replaceAll(key, renderMap[key]);
            }
            return code;
        },
        renderKeys(code) {
            let keys = abapKeywords; // 替换关键字
            for (let i = 0; i < keys.length; i++) {
                let key = this.getMap(`<span class="abap-code-keys">${keys[i]}</span>`);
                code = code.replaceAll(`${keys[i]}`, key);
            }
            return code;
        },
        renderChars(code) {
            let chars = [':', '.', ',', '=']; // 替换标点符号
            for (let i = 0; i < chars.length; i++) {
                let key = this.getMap(`<span class="abap-code-chars">${chars[i]}</span>`);
                code = code.replaceAll(`${chars[i]}`, key);
            }
            return code;
        },
        renderNotes(code) {
            let lines = code.split(`\n`);
            let newCodeArr = [];
            let patt = new RegExp('(\\*|\\").*'); // 替换的注释
            for (let j = 0; j < lines.length; j++) {
                let res = patt.exec(lines[j]);
                if (res != null) {
                    let key = this.getMap(`<span class="abap-code-notes">${res[0]}</span>`);
                    newCodeArr.push(lines[j].replaceAll(`${res[0]}`, key));
                } else {
                    newCodeArr.push(lines[j]);
                }
            }
            return newCodeArr.join("\n");
        },
        renderNumber(code) {
            let lines = code.split(`\n`);
            let newCodeArr = [];
            for (let i = 0; i < lines.length; i++) {
                let line = lines[i];
                let res = line.match(/ (\d+)/g); // 【 123123】形式
                let lengthTypeRes = line.match(/\(\d+\)/g); // 【(123)】形式
                if (res == null) {
                    res = [];
                }
                if (lengthTypeRes == null) {
                    lengthTypeRes = [];
                }
                let newRes = res.concat(lengthTypeRes);

                if (newRes == null || newRes.length < 1) {
                    newCodeArr.push(line);
                    continue;
                }
                for (let j = 0; j < newRes.length; j++) {
                    let key = this.getMap(`<span class="abap-code-number">${newRes[j]}</span>`);
                    line = line.replaceAll(`${newRes[j]}`, key);
                }
                    newCodeArr.push(line);
            }
            return newCodeArr.join("\n");
        },
        renderString(code) {
            let lines = code.split(`\n`);
            let newCodeArr = [];
            for (let i = 0; i < lines.length; i++) {
                let line = lines[i];
                let res = line.match(/'(\w|\d|_)+'/g);
                if (res == null || res.length < 1) {
                    newCodeArr.push(line);
                    continue;
                }
                for (let j = 0; j < res.length; j++) {
                    let key = this.getMap(`<span class="abap-code-string">${res[j]}</span>`);
                    line = line.replaceAll(`${res[j]}`, key);
                }
                newCodeArr.push(line);
            }
            return newCodeArr.join("\n");
        },
    }
}
</script>

<style>
.abap-code-keys {
    color: #0000FF;
}

.abap-code-chars {
    color: #800080;
}

.abap-code-notes {
    color: #c0c4cc;
}

.abap-code-number {
    color: #3399FF;
}

.abap-code-string {
    color: #4DA619;
}

.abap-code-values {
    color: #4DA619;
}

.abap-api-item-group {
    font-weight: bold;
}
.abap-api-item {
    width: 100%;
    float: left;
    display: flex;
}
.abap-api-item-2 {
    width: 50%;
    float: left;
    display: flex;
}
.abap-api-item .el-checkbox__label {
    width: 65px;
}
.abap-api-item > div:first-child,
.abap-api-item-2 > div:first-child{
    width: 60px;
    float: left;
    font-size: 14px;
    display: flex;
    align-items: center;
}
.abap-api-item > div:last-child,
.abap-api-item-2 > div:last-child {
    float: left;
    flex: 1;
    padding-right: 15px;
}
</style>
<style scoped>
.dev-container {
    height: 100%;
    background-color: white;
}

.dev-left-panel {
    width: 400px;
}

.dev-right-panel {
    width: 450px;
}

.dev-right-panel /deep/ .el-form-item {
    margin-bottom: 12px;
}

.dev-left-panel /deep/ .el-tabs__header {
    margin: 0px;
}

.dev-main-panel {
    height: 100%;
    width: 100%;
}

.dev-collapse-title {
    font-weight: bold;
    font-size: 13px;
    padding: 0px 8px;
}

.dev-comp-item {
    padding: 3px 5px;
    background: #f6f7ff;
    font-size: 12px;
    cursor: pointer;
    border: 1px solid #f6f7ff;
    border-radius: 3px;
    width: 44%;
    margin-left: 4%;
    float: left;
}

.dev-comp-item:hover {
    border: 1px solid #787be8;
    color: #787be8;
}

.dev-code {
    color: #000000;
    border-radius: 4px;
    padding: 5px;
    white-space: pre;
    width: fit-content;
    font-family: 新宋体;
}

</style>
