<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="name0" :stretch="true">
                <template v-for="(tab,cptIndex) in cptList">
                    <el-tab-pane v-if="tab.fdType == 1" :label="tab.fdName" :name="'name' + cptIndex">
                        <template v-for="menu in tab.children">
                            <el-collapse value="itemName">
                                <el-collapse-item v-if="menu.fdType == 2" :title="menu.fdName" name="itemName">
                                    <template slot="title">
                                        <span class="dev-collapse-title">{{ menu.fdName }}</span>
                                    </template>
                                    <template v-for="(item,index) in menu.children">
                                        <div v-if="item.fdType == 3" class="dev-panel-item">
                                            <div class="dev-comp-item" :data-type="item.fdId"
                                                 @click="clickItemEvent(item.fdId)">
                                                <i :class="item.fdIcon"/>&nbsp;{{ item.fdName }}
                                            </div>
                                        </div>
                                    </template>
                                </el-collapse-item>
                            </el-collapse>
                        </template>
                    </el-tab-pane>
                </template>
            </el-tabs>
        </div>

        <!--中间面板-->
        <div class="flex-1 flex flex-direction-column" style="overflow: auto;">
            <ap-container>
                <ap-header margin="0111" height="40%" style="overflow: auto;">
                    <template v-if="showItem">
                        <!--                        <dynamic-item/>-->
                        <vue-render :options.sync="vueCode"></vue-render>
                    </template>
                    <template v-else>
                        组件加载中...
                    </template>
                </ap-header>
                <ap-main margin="0101" style="overflow: auto;background-color: #f9f2f4;">
                    <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">
                        {{ template }}
                    </div>
                </ap-main>
            </ap-container>
        </div>

        <!--右侧面板-->
        <div class="dev-container dev-right-panel flex flex-direction-column">
            <div class="flex-1" style="overflow: auto">
                <el-tabs value="name0" :stretch="true">
                    <template v-for="(tab,paramIndex) in paramTabList">
                        <el-tab-pane :label="tab" :name="'name' + paramIndex" style="padding-left: 10px;">
                            <template v-for="param in paramList">
                                <el-form v-if="param.fdTab == tab" label-position="left" label-width="130px">
                                    <template
                                        v-if="checkShowCondition(param) && (param.fdParentId == null || param.fdParentId == '')">
                                        <el-form-item v-if="param.fdShowType == 1" :label="param.fdName"
                                                      :prop="param.fdAttrName">
                                            <el-input v-model="param.value" :placeholder="param.fdPlaceholder"
                                                      style="width: 280px;" @input="changeEvent(param)"/>
                                        </el-form-item>

                                        <el-form-item v-if="param.fdShowType == 2" :label="param.fdName"
                                                      :prop="param.fdAttrName">
                                            <el-switch v-model="param.value" active-value="1" inactive-value="0"
                                                       @change="changeEvent(param)"/>
                                        </el-form-item>

                                        <el-form-item v-if="param.fdShowType == 3" :label="param.fdName"
                                                      :prop="param.fdAttrName">
                                            <el-select v-model="param.value" @input="changeEvent(param)">
                                                <template v-for="option in handelOption(param)">
                                                    <el-option :label="option.label" :value="option.value"/>
                                                </template>
                                            </el-select>
                                        </el-form-item>

                                        <el-form-item v-if="param.fdShowType == 4" :label="param.fdName"
                                                      :prop="param.fdAttrName">
                                            <el-button size="mini" type="primary" plain @click="openDialog(param)"
                                                       style="padding: 4px 10px;"><i class="el-icon-s-tools"/> 配置
                                            </el-button>
                                            <template v-for="item in handelArrValue(param)">
                                                <el-input :value="item" :readonly="true" style="width: 280px">
                                                    <el-button slot="append" icon="el-icon-edit-outline"  @click="openEditDialog(param)"></el-button>
                                                </el-input>
                                            </template>
                                        </el-form-item>

                                        <el-form-item v-if="param.fdShowType == 5" :label="param.fdName"
                                                      :prop="param.fdAttrName">
                                            <el-radio-group v-model="param.value" @change="changeEvent(param)">
                                                <template v-for="option in handelOption(param)">
                                                    <el-radio :label="option.value">{{ option.label }}</el-radio>
                                                </template>
                                            </el-radio-group>
                                        </el-form-item>

                                        <el-form-item v-if="param.fdShowType == 6" :label="param.fdName"
                                                      :prop="param.fdAttrName">
                                            <el-input type="textarea" v-model="param.value"
                                                      :placeholder="param.fdPlaceholder" :rows="2" style="width: 280px;"
                                                      @input="changeEvent(param)"/>
                                        </el-form-item>

                                        <el-form-item v-if="param.fdShowType == 7" :label="param.fdName"
                                                      :prop="param.fdAttrName">
                                            <el-input-number v-model="param.value" @change="changeEvent(param)"
                                                             :min="handelOptionObj(param).min"
                                                             :max="handelOptionObj(param).max"
                                                             label="描述文字"></el-input-number>
                                        </el-form-item>

                                        <div v-if="param.fdShowLine == 1" class="ap-split-line"/>
                                    </template>
                                </el-form>
                            </template>
                        </el-tab-pane>
                    </template>
                </el-tabs>
            </div>
        </div>

        <!-- 数组参数弹框 -->
        <el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="600px">
            <template v-for="param in paramList">
                <el-form label-position="left" label-width="120px">
                    <template v-if="checkShowCondition(param)  && (param.fdParentId == currentArrayParam.fdId)">
                        <el-form-item v-if="param.fdShowType == 1" :label="param.fdName" :prop="param.fdAttrName">
                            <el-input v-model="param.value" :placeholder="param.fdPlaceholder" style="width: 440px;"
                                      @input="changeEvent(param)"/>
                        </el-form-item>

                        <el-form-item v-if="param.fdShowType == 2" :label="param.fdName" :prop="param.fdAttrName">
                            <el-switch v-model="param.value" active-value="1" inactive-value="0"
                                       @change="changeEvent(param)"/>
                        </el-form-item>

                        <el-form-item v-if="param.fdShowType == 3" :label="param.fdName" :prop="param.fdAttrName">
                            <el-select v-model="param.value" @input="changeEvent(param)">
                                <template v-for="option in handelOption(param)">
                                    <el-option :label="option.label" :value="option.value"/>
                                </template>
                            </el-select>
                        </el-form-item>

                        <el-form-item v-if="param.fdShowType == 4" :label="param.fdName" :prop="param.fdAttrName">
                            <el-button size="mini" type="primary" plain @click="openDialog(param)"><i
                                class="el-icon-plus"/></el-button>
                            <template v-for="item in param.arrValue">
                                <el-input :value="item">
                                    <el-button slot="append" icon="el-icon-search" @click="openEditDialog(param)"></el-button>
                                </el-input>
                            </template>
                        </el-form-item>

                        <el-form-item v-if="param.fdShowType == 5" :label="param.fdName" :prop="param.fdAttrName">
                            <el-radio-group v-model="param.value" @change="changeEvent(param)">
                                <template v-for="option in handelOption(param)">
                                    <el-radio :label="option.value">{{ option.label }}</el-radio>
                                </template>
                            </el-radio-group>
                        </el-form-item>

                        <el-form-item v-if="param.fdShowType == 6" :label="param.fdName" :prop="param.fdAttrName">
                            <el-input type="textarea" v-model="param.value" :placeholder="param.fdPlaceholder" :rows="4"
                                      style="width: 440px;" @input="changeEvent(param)"/>
                        </el-form-item>

                        <el-form-item v-if="param.fdShowType == 7" :label="param.fdName" :prop="param.fdAttrName">
                            <el-input-number v-model="param.value" @change="changeEvent(param)"
                                             :min="handelOptionObj(param).min" :max="handelOptionObj(param).max"
                                             label="描述文字"></el-input-number>
                        </el-form-item>

                        <div v-if="param.fdShowLine == 1" class="ap-split-line"/>
                    </template>
                </el-form>
            </template>
            <span slot="footer">
                <el-button @click="dialogVisible = false">取 消</el-button>
                <el-button type="danger" @click="delArrayParam">删 除</el-button>
                <el-button type="primary" @click="saveArrayParam">确 定</el-button>
            </span>
        </el-dialog>
    </div>
</template>

<script>
import VueRender from './../base/VueRender'
import clipboard from 'ap-util/util/ClipboardUtil'
import {convertToTreeData} from 'ap-util/util/DataUtil'


export default {
    name: 'ComponentsPanel',
    components: {
        VueRender: VueRender
    },
    data() {
        return {
            showItem: true,
            vueCode: '',
            cptList: [], // 组件清单列表
            cptInfo: {}, // 组件信息
            baseInfo: {}, // 组件基础模板信息
            cptTemplateList: [], // 组件模板列表
            cptTemplateObj: {}, // 组件模板对象
            paramTabList: [], // 参数页签列表
            paramList: [], // 参数列表
            paramObj: [], // 参数对象
            paramTemplateList: [], // 参数模板列表
            paramTemplateObj: {}, // 参数模板对象
            template: '', // 代码

            dialogTitle: '',
            dialogVisible: false,
            currentArrayParam: {}, // 当前数组参数
            currentArrayParamObj: {}, // 当前数组参数：保留参数信息用于编辑
            arrayParamList: [], // 数组参数列表
            arrayParamTemplateList: [], // 数组参数模板列表
        }
    },
    computed: {},
    created() {
        this.getDevCpt();
    },
    methods: {
        getDevCpt() {
            this.$request({
                url: '/apd/cpt/TDevCpt/getCptList',
                method: 'post',
                data: {}
            }).then(response => {
                this.cptList = convertToTreeData(response.data, {
                    idKey: 'fdId',
                    parentKey: 'fdParentId',
                    childrenKey: 'children'
                });
            })
        },
        clickItemEvent(id) {
            this.$request({
                url: '/apd/cpt/TDevCpt/getDevCptInfo',
                method: 'post',
                data: {
                    id: id
                }
            }).then(response => {
                let data = response.data;
                this.getParamTabList(data.paramList);
                this.cptInfo = data.cptInfo;
                this.baseInfo = data.baseInfo;
                this.paramList = this.initParam(data.paramList);
                this.paramTemplateList = data.paramTemplateList;
                this.cptTemplateList = data.cptTemplateList;
                this.renderTemplate();
            })
        },
        getParamTabList(list) {
            let tabNameList = [];
            for (let i = 0; i < list.length; i++) {
                tabNameList.push(list[i].fdTab);
            }
            this.paramTabList = Array.from(new Set(tabNameList));
        },
        // 参数选项值转为数组
        handelOption(param) {
            let options = param.fdOption;
            if (options == null || options == "") {
                return [];
            }
            let res = [];
            let opts = options.split("##");
            for (let i = 0; i < opts.length; i++) {
                let opt = opts[i].split("::");
                let valueStr = opt.length > 1 ? opt[1] : opt[0];
                res.push({
                    label: opt[0],
                    value: valueStr
                })
            }
            return res;
        },
        // 参数选项值转为对象
        handelOptionObj(param) {
            let opts = this.handelOption(param);
            let res = {};
            for (let i = 0; i < opts.length; i++) {
                res[opts.label] = opts.value;
            }
            return res;
        },
        // 初始化参数信息：value
        initParam(paramList) {
            // 处理参数的fdValue
            for (let i = 0; i < paramList.length; i++) {
                this.handelValue(paramList[i]);
            }
            return paramList;
        },
        // 初始设定参数的value：fdValue转为value
        handelValue(param) {
            let fdValue = param.fdValue;
            // 字符串形式
            if (param.fdShowType != 4) {
                param.value = fdValue;
                return;
            }

            // 数组形式
            if (fdValue == null || fdValue == "") {
                param.arrValue = [];
                param.value = "";
                return;
            }
            let res = [];
            let opts = fdValue.split("##");
            for (let i = 0; i < opts.length; i++) {
                let opt = opts[i].split("::");
                if (opt.length <= 1) {
                    // 字符串参数
                    res.push(opt[0]);
                } else {
                    // 对象参数
                    let obj = {};
                    obj[opt[0]] = opt[1];
                    res.push(obj);
                }
            }
            param.arrValue = res;
            param.value = `[ ${res.join(", ")} ]`;
        },
        handelArrValue(param) {
            // 替换参数
            let value = this.replaceTemplateParam(param.fdValue);
            let res = [];
            let values = value.split("##");
            for (let i = 0; i < values.length; i++) {

                let item = {};
                let objs = values[i].split(",,");
                for (let j = 0; j < objs.length; j++) {
                    if (objs[j].indexOf("::") > 0) {
                        res.push(objs[j]);
                    } else {
                        let obj = objs[j].split("::");
                        item[obj[0]] = item[obj[1]];
                    }
                }
                res.push(item);
            }

            return res;
        },
        // 判定是否显示参数
        checkShowCondition(param) {
            let showCondition = param.fdShowCondition;
            if (showCondition == null || showCondition == "") {
                return true;
            }
            let condition = this.replaceTemplateParam(showCondition);
            return eval(condition);
        },
        // 判定是否添加参数到代码
        checkAddCondition(addCondition) {
            if (addCondition == null || addCondition == "") {
                return true;
            }
            let condition = this.replaceTemplateParam(addCondition);
            return eval(condition);
        },
        // 判定是否使用默认参数
        checkDefaultCondition(defaultCondition) {
            if (defaultCondition == null || defaultCondition == "") {
                return false;
            }
            let condition = this.replaceTemplateParam(defaultCondition);
            return eval(condition);
        },
        // 模板赋值 -> type:1参数模板 2组件模板
        handleTemplate(template, type) {
            let res = "";

            // 判断是否添加模板
            if (!this.checkAddCondition(template.fdAddCondition)) {
                return "";
            }

            // 判断是否使用默认模板
            if (this.checkDefaultCondition(template.fdDefaultCondition)) {
                res = template.fdDefault;
            } else {
                res = template.fdTemplate;
            }

            // 参数模板
            if (type == 1) {
                return this.replaceTemplateParam(res);
            }

            // 组件模板
            if (type == 2) {
                return this.replaceTemplateCpt(res);
            }

        },
        changeEvent(param) {
            this.renderTemplate();
        },
        // 渲染代码
        renderTemplate() {
            // 设定参数对象
            this.initParamObj();

            // 设定参数模板
            this.initParamTemplate()

            // 设定组件模板
            this.initCptTemplate();

            // 设定组件基础模板
            this.initBaseTemplate();

        },
        // 设定参数对象
        initParamObj() {
            let paramList = this.paramList;

            // 设定参数对象
            let param = {};
            for (let i = 0; i < paramList.length; i++) {
                param[paramList[i].fdCode] = {
                    value: paramList[i].value,
                    defaultCondition: paramList[i].fdDefaultCondition,
                }
            }
            this.paramObj = param;
            console.log("paramObj: 参数对象");
            console.log(param);
        },
        // 替换模板中的参数
        replaceTemplateParam(template) {
            if (template == null) {
                return "";
            }
            // 正则参数：例：${InputChangeEvent.value}
            let reg = new RegExp(/\${\w*\.\w*}/g);
            let paramArr = template.match(reg);
            if (paramArr == null) {
                return template;
            }
            for (let j = 0; j < paramArr.length; j++) {
                let pTemp = paramArr[j].substring(2, paramArr[j].length - 1).split(".");
                // 参数实际值
                let paramValue = this.paramObj[pTemp[0]];
                let replaceStr = "";
                if (paramValue == null) {
                    replaceStr = `###error: 获取参数对象为空 ${paramArr[j]}###`;
                } else {
                    let value = paramValue[pTemp[1]];
                    if (value == null || value == "") {
                        replaceStr = "";
                    } else {
                        replaceStr = value;
                    }
                }
                template = template.replaceAll(paramArr[j], replaceStr);
            }
            return template;
        },
        // 替换组件模板的参数
        replaceTemplateCpt(template) {
            if (template == null) {
                return "";
            }

            // 正则参数：例：${attrs}
            let reg = new RegExp(/\${\w*}/g);
            // 正则参数：例：${attrs#,}
            let regCustom = new RegExp(/\${\w*#[^$]*}/g);

            // 参数赋值：数组默认拼接
            let paramArr = template.match(reg);
            if (paramArr != null) {
                for (let j = 0; j < paramArr.length; j++) {
                    // 参数实际值
                    let attrName = paramArr[j].substring(2, paramArr[j].length - 1);
                    let valueObj = this.paramTemplateObj[attrName];
                    if (valueObj == null) {
                        // 不存在参数数组，替换为空
                        template = template.replaceAll(paramArr[j], "");
                    } else {
                        template = template.replaceAll(paramArr[j], valueObj.join(" "));
                    }

                }
            }

            // 参数赋值：数组自定义拼接
            let paramArr2 = template.match(regCustom);
            if (paramArr2 != null) {
                for (let j = 0; j < paramArr2.length; j++) {
                    // 参数实际值
                    let attrName = paramArr2[j].substring(2, paramArr2[j].length - 1).split("#");
                    let valueObj = this.paramTemplateObj[attrName[0]];
                    if (valueObj == null) {
                        // 不存在参数数组，替换为空
                        template = template.replaceAll(paramArr2[j], "");
                    } else {
                        template = template.replaceAll(paramArr2[j], valueObj.join(attrName[1]));
                    }
                }
            }

            return template;
        },
        // 设定参数模板
        initParamTemplate() {
            let templates = this.paramTemplateList;

            for (let i = 0; i < templates.length; i++) {
                templates[i].template = this.handleTemplate(templates[i], 1);
            }

            // 参数模板对象
            let templateObj = {};
            for (let i = 0; i < templates.length; i++) {
                let paramName = templates[i].fdParamName;
                if (templateObj[paramName] == null) {
                    templateObj[paramName] = [];
                }
                templateObj[paramName].push(templates[i].template);
            }

            this.paramTemplateObj = templateObj;
            // console.log("paramTemplateObj: 参数模板对象");
            // console.log(templateObj);
        },
        // 设定组件模板
        initCptTemplate() {
            let templates = this.cptTemplateList;
            for (let i = 0; i < templates.length; i++) {
                templates[i].template = this.handleTemplate(templates[i], 2);
            }

            // 组件模板对象
            let templateObj = {};
            for (let i = 0; i < templates.length; i++) {
                let paramName = templates[i].fdParamName;
                if (templateObj[paramName] == null) {
                    templateObj[paramName] = [];
                }
                templateObj[paramName].push(templates[i].template);
            }

            this.cptTemplateObj = templateObj;
            // console.log("cptTemplateObj: 组件模板");
            // console.log(this.cptTemplateObj);
        },
        // 设定组件基础模板
        initBaseTemplate() {
            let baseInfo = this.baseInfo;
            let cptTemplateObj = this.cptTemplateObj;
            // 正则参数：例：${attrs}
            let reg = new RegExp(/\${\w*}/g);
            // 正则参数：例：${attrs#,}
            let regCustom = new RegExp(/\${\w*#[^}]*}/g);
            let template = this.baseInfo.fdTemplate;
            if (template == null) {
                template = "组件的基础模板不存在";
                return;
            }
            // 参数赋值：数组默认拼接
            let paramArr = template.match(reg);
            if (paramArr != null) {
                for (let j = 0; j < paramArr.length; j++) {
                    // 参数实际值
                    let attrName = paramArr[j].substring(2, paramArr[j].length - 1);
                    let valueObj = cptTemplateObj[attrName];
                    if (valueObj == null) {
                        // 不存在参数数组，替换为空
                        template = template.replaceAll(paramArr[j], "");
                    } else {
                        template = template.replaceAll(paramArr[j], valueObj.join(" "));
                    }

                }
            }

            // 参数赋值：数组自定义拼接
            let paramArr2 = template.match(regCustom);
            if (paramArr2 != null) {
                for (let j = 0; j < paramArr2.length; j++) {
                    // 参数实际值
                    let attrName = paramArr2[j].substring(2, paramArr2[j].length - 1).split("#");
                    let valueObj = cptTemplateObj[attrName[0]];
                    if (valueObj == null) {
                        // 不存在参数数组，替换为空
                        template = template.replaceAll(paramArr2[j], "");
                    } else {
                        template = template.replaceAll(paramArr2[j], valueObj.join(attrName[1]));
                    }
                }
            }
            this.template = template;

            // console.log("cptTemplateObj: 组件模板对象");
            // console.log(this.cptTemplateObj);
            this.vueCode = this.template;
        },
        renderCode() {
            this.vueCode = this.template;
        },
        copyCode(event) {
            clipboard(this.vueCode, event)
        },
        openDialog(param) {
            this.dialogTitle = param.fdName;
            this.dialogVisible = true;
            this.currentArrayParam = param;
        },
        openEditDialog(param) {
            this.dialogTitle = param.fdName;
            this.dialogVisible = true;
            this.currentArrayParam = param;
            // 参数赋值
            console.log(this.currentArrayParamObj);
        },
        // 删除数组参数
        delArrayParam() {

        },
        // 返回当前数组参数的子参数
        getCurrentArrayParam() {
            let id = this.currentArrayParam.fdId;
            let arrParam = [];
            let paramList = this.paramList;
            for (let i = 0; i < paramList.length; i++) {
                if (paramList[i].fdParentId == id) {
                    arrParam.push(paramList[i]);
                }
            }

            return arrParam;
        },
        handleStr() {

        },
        getCurrentArrayParamObj() {
            let arrParam = this.getCurrentArrayParam();
            let obj = {};
            for (let i = 0; i < arrParam.length; i++) {
                obj[arrParam[i].fdCode] = arrParam[i].value;
            }
            this.currentArrayParamObj = obj;
        },
        // 返回当前数组参数的子参数模板
        getCurrentArrayParamTemplate() {
            this.currentArrayParamObj = {};
            let arrParam = this.getCurrentArrayParam();
            let pValue = this.currentArrayParam.arrValue;
            if (arrParam == null || arrParam.length < 1) {
                return pValue;
            }
            let itemInfo = [];
            let templates = this.paramTemplateList;
            for (let i = 0; i < arrParam.length; i++) {
                for (let j = 0; j < templates.length; j++) {
                    if (templates[j].fdParamId == arrParam[i].fdId) {
                        let tmp = this.handleTemplate(templates[j], 1);
                        if (tmp != null && tmp != "") {
                            itemInfo.push(tmp);
                        }
                    }
                }
            }
            if (itemInfo.length < 1) {
                return pValue;
            }
            console.log(111);
            let item = "";
            if (itemInfo.length == 1) {
                if (itemInfo[0].indexOf(": ") > -1) {
                    // 对象参数
                    item = `{ ${itemInfo.join(",")} } `;
                } else {
                    // 非对象类型
                    item = itemInfo[0];
                }
            }
            if (itemInfo.length > 1) {
                item = `{ ${itemInfo.join(",")} } `;
            }
            pValue.push(item);
            this.currentArrayParam.value = `[ ${pValue.join(", ")} ]`;
        },
        // 保存数组参数
        saveArrayParam() {
            this.getCurrentArrayParamTemplate();
            this.renderTemplate();
            this.getCurrentArrayParamObj();
        }
    }


}
</script>

<style scoped>
.dev-container {
    height: 100%;
    background-color: white;
}

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

.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: 5px 8px;
    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: #c7254e;
    border-radius: 4px;
    padding: 5px;
    white-space: pre;
    width: fit-content;
}
</style>
