<template>
    <div>
        <div class="form">
            <form-control
                class="form-control"
                :toc="toc"
                :data-list="list"
                :applicable="applicable"
                @add="$refs.view.clickAdd($event)"
                @start="$refs.view.isDraging = true"
                @end="$refs.view.isDraging = false"
            ></form-control>
            <form-view
                class="form-view"
                :applicable="applicable"
                :list="list"
                :list-item="item"
                :list-index.sync="index"
                :list-sub-index.sync="subIndex"
                ref="view"
                @update="getItem"
                @forceUpdate="$refs.edit.forceUpdate()"
            >
                <slot name="header"></slot>
            </form-view>
            <form-edit
                class="form-edit"
                :applicable="applicable"
                :list="list"
                :item="item"
                :index="index"
                :sub-index="subIndex"
                ref="edit"
            ></form-edit>
        </div>
        <div class="footer" v-if="!hideBtn">
            <slot name="before"></slot>
            <slot>
                <el-button type="primary" @click="submit">{{ btnText }}</el-button>
            </slot>
            <slot name="after"></slot>
        </div>
    </div>
</template>

<script>
import { mapMutations } from 'vuex'
import { v1 as uuidv1 } from 'uuid'
export default {
    name: 'FormDesign',
    components: {
        FormControl: () => import('./components/FormControl'),
        FormView: () => import('./components/FormView'),
        FormEdit: () => import('./components/FormEdit')
    },
    props: {
        formId: { type: String, default: '' }, // 表单 id
        category: { type: String, default: '' }, // 表单类型
        sourceId: { type: String, default: '' }, // 关联的来源 id
        applicable: { type: String, default: 'Form' }, // 控件类型，可选 Form 和 Question
        btnText: { type: String, default: '保存' }, // 保存按钮文字
        hideBtn: { type: Boolean, default: false }, // 是否隐藏保存按钮
        toc: { type: Boolean, default: false }, // 左边的控件区域是否显示切换大纲
        format: { type: Function, default: list => list } // 处理初始化控件列表方法
    },
    data () {
        return {
            list: [], // 表单内容
            item: {}, // 当前控件
            index: -1, // 当前控件索引
            subIndex: -1 // 当前控件索引
        }
    },
    watch: {
        // list 的变动比 index 快，只能监听 index 来获取当前 item
        index (value) {
            this.getItem()
            this.saveIndex(value)
        },
        subIndex (value) {
            this.getItem()
            this.saveSubIndex(value)
        }
    },
    created () {
        if (this.formId) this.getList()
    },
    methods: {
        ...mapMutations(['saveList', 'saveIndex', 'saveSubIndex', 'saveFormItem']),
        // 编辑时获取表单列表
        getList () {
            this.$api.commonApi.formInfoGet({
                b_id: this.formId
            }).then(res => {
                if (res.data.Status) {
                    this.list = this.format(JSON.parse(res.data.Data.content))
                }
            })
        },
        // 返回 item
        getItem () {
            this.item = this.index === -1
                ? {}
                : this.subIndex === -1
                    ? this.list[this.index]
                    : this.list[this.index].list[this.subIndex]
            this.saveFormItem(this.item)
            this.saveList(this.list)
        },
        // 检测计算公式的对象是否有效
        verifyCalculate () {
            this.list.forEach((item, index) => {
                if (item.type === 'calculate') this.$refs.edit.verifyCalculate(item, true)
                if (item.type === 'subform') {
                    item.list.forEach(n => {
                        if (n.type === 'calculate') this.$refs.edit.verifyCalculate(n, true)
                    })
                }
            })
        },
        // 验证
        verify (list, isSub) {
            for (let i = 0; i < list.length; i++) {
                const item = list[i]
                // 先判断子表单可以先设置 index 不必传参
                if (item.type === 'subform') {
                    this.index = i
                    if (!this.verify(item.list, true)) return false
                }
                for (let key in item) {
                    if (key.includes('Error') && item[key]) {
                        // 如果当前控件就是错误控件需强制刷新
                        if ((this.index === i && this.subIndex === -1) || (isSub && this.subIndex === i)) {
                            this.$refs.edit.forceUpdate()
                        } else {
                            if (!isSub) {
                                this.index = i
                                this.subIndex = -1
                            } else {
                                this.subIndex = i
                            }
                        }
                        this.$message.warning('控件的配置有误')
                        return false
                    }
                }
            }
            return true
        },
        // 清除不必要的验证属性
        clearError (list = this.list) {
            list.forEach((item, index) => {
                for (let key in item) if (key.includes('Error')) delete item[key]
                if (item.type === 'subform') this.clearError(item.list)
                if (this.applicable === 'Question' && 'nth' in item) delete item.nth
            })
        },
        // 提交
        submit () {
            if (!this.list.length) {
                this.$message.warning('请添加控件')
            } else {
                this.verifyCalculate()
                // 验证时会改变 index，所以通过后需改回来
                const index = this.index
                const subIndex = this.subIndex
                if (this.verify(this.list)) {
                    this.index = index
                    this.subIndex = subIndex
                    this.clearError()
                    !this.formId ? this.created() : this.update()
                }
            }
        },
        // 获取参数
        getParams () {
            return {
                category: this.category,
                source_id: this.sourceId,
                content: JSON.stringify(this.list)
            }
        },
        // 创建
        created () {
            this.$api.commonApi.formInfoCreate({
                b_id: uuidv1(),
                ...this.getParams()
            }).then(res => {
                if (res.data.Status) this.$emit('submit', res.data.Data)
            })
        },
        // 修改
        update () {
            this.$api.commonApi.formInfoUpdate({
                b_id: this.formId,
                ...this.getParams()
            }).then(res => {
                if (res.data.Status) this.$emit('submit')
            })
        }
    }
}
</script>

<style lang="less" scoped>
.form {
    display: flex;
    overflow-x: auto;
    color: #333;
    .form-control, .form-view, .form-edit {
        border: 1px solid #E4E7ED;
    }
    .form-control, .form-edit {
        width: 400px;
        height: 709px;
        flex-shrink: 0;
        overflow-y: auto;
    }
    .form-view {
        flex-grow: 1;
        min-width: 580px;
        margin: 0 20px;
    }
}
.footer {
    padding-top: 15px;
    text-align: center;
}
</style>
