/**
 * 元素布局模板组件
 * 目标: 简化元素布局逻辑
 * @author xiufu.wang
 */
import ElRow from 'mars-pro/packages/row';
import ElCol from 'mars-pro/packages/col';
import { objectProperty } from 'mars-pro/src/pro/util';
import { getAllChildren, getAllProps, cloneElement } from 'mars-pro/src/pro/vue-util';

function isHiddenVnode(vNode) {
    let showDirec = objectProperty(vNode, 'data.directives', []).filter(r => r.name === 'show')
    if (showDirec.length > 0) {
        return !(showDirec[0].value)
    }
    return false
}

export default {
    name: 'ProLayoutContaner',
    componentName: 'ProLayoutContaner',
    components: {
        ElRow,
        ElCol
    },
    props: {
        // 是否换行
        flexNowrap: {
            type: Boolean,
            default: false
        },
        //默认列数
        columnCount: {
            type: Number,
            default: 3
        },
        //默认flex
        flex: [String, Number],
        //是否开启懒渲染模式: true 如果初始渲染子元素v-show为false,则不渲染
        optimizationLazy: {
            type: Boolean,
            default: true
        },
        enableBottomGutter: {
            type: Boolean,
            default: true
        }
    },
    created() {
        this.renderCache = {}
    },
    computed: {
        // 样式
        wapperCls() {
            return {
                'pro-layout-contaner': true,
                'pro-layout-contaner--nowrap': this.flexNowrap === true,
                'pro-layout-contaner--wrap': this.flexNowrap !== true
            }
        }
    },
    methods: {
        parseFlex(flex) {
            // 自使用 :flex="1"
            if (typeof flex === 'number') {
                return `${flex} ${flex} auto`;
            }
            //固定宽度
            if (/^\d+(\.\d+)?(px|em|rem|%)$/.test(flex)) {
                return `0 0 ${flex}`;
            }
            return flex;
        },
        renderWapperCol() {
            const childrens = getAllChildren(this).filter(r => !!(r.tag))
            if (!childrens) {
                return null
            }
            const columns = this.columnCount > 0 ? this.columnCount : 3
            const perSpan = (24 / columns) | 0
            return childrens.map(child => {
                const isElCol = objectProperty(child, 'componentOptions.Ctor.sealedOptions.name', '') === 'ElCol'
                const isHide = isHiddenVnode(child)
                const childAttrs = getAllProps(child)
                const childKey = objectProperty(child, 'data.key')
                const flex = childAttrs.flex || this.flex
                if (childKey && isHide && !this.renderCache[childKey]) {
                    return null
                }
                if (childKey && this.optimizationLazy) {
                    if (isHide && !this.renderCache[childKey]) {
                        return null
                    }
                    this.renderCache[childKey] = true
                }

                const colStyle = {
                    ...(flex && flex !== 'none' ? { flex: this.parseFlex(flex) } : {}),
                    ...((this.$attrs.gutter && this.enableBottomGutter) ? { marginBottom: `${this.$attrs.gutter}px` } : {})
                }
        
                const colDatas = {
                    props: {
                        span: flex ? null : (childAttrs.span || perSpan),
                        offset: childAttrs.offset,
                        push: childAttrs.push,
                        pull: childAttrs.pull
                    },
                    key: childKey,
                    style: colStyle,
                    'class': {
                        'pro-layout-contaner-item': true,
                        'pro-layout-contaner-item--hiden': isHide,
                        [`${childKey || ''}--item`]: !!childKey
                    }
                }

                if (isElCol) {
                    return cloneElement(child, colDatas)
                } else {
                    return (<ElCol
                        {...colDatas}
                    >{child}</ElCol>)
                }
            })
        }
    },
    render() {
        const _datas = {
            'class': this.wapperCls,
            props: {
                type: 'flex',
                ...this.$attrs,
            }
        }
        return (
            <ElRow {..._datas}>{this.renderWapperCol()}</ElRow>
        )
    }
}