<template lang="pug">
    .oc-tree-select-container.vm(ref="dropContainer", tabindex="-1", @blur.capture="_blurHandler($event)", :disabled="disabled", @mouseenter="handlehoverClearIcon", @mouseleave="handlehideHoverClearIcon")
        .pr.h
            select.ocFormElement(ref="ocFormElement", :name="name", tabindex="-1", :required="required", :multiple="multiple")
                option(:selected="true", v-for="id in selected", :value="id", :disabled="disabled")
            .oc-ipt-result(@focus.capture="show($event)", :class="{ multipleLine: isMultipleLine, showClearAll: isShowClearAll && !disabled }", :style="iptStyle", tabindex="0", ref="ipt", :disabled="disabled")
                i.oc-select-clear-icon.fa.fa-times-circle(v-if="isShowClearAll && !disabled", tabindex="1", @click="handleClear")
                span.oc-ipt-result-item(v-for="id in selected", tabindex="-1", :title="getSelectedFullText(id)", :data-id="id") {{getSelectedText(id)}}
                    i(tabindex="-1", @click.stop.prevent="remove(id)", v-if="!disabled") ×
        
        div.f12.formSm.pt10.divPropsContainer(ref="divProps", v-show="activePropId !== null")
            p.pl15.fb.pb10.mb10(style="border-bottom: 1px solid #eee;") {{$t('_ocui_current_issue')}}：{{activePropName}}
            div.divPropsItem.pb5(v-for="item in formatedNodeProperties", style="display: inline-block;")
                span.divProsItemLabel(style="padding-left:10px; margin-right: 0; display: inline-block; width: 100px; overflow: hidden; vertical-align:middle; word-break: break-word", :class="{ must: item[requiredKey] && toBoolean(item[isSystemPropertyKey]) }") {{item[propertyNameKey] + ':'}}
                oc-select.w150(:items="item[propertyValueKey]", :name="item[propertyKey]", :isAll="true", :value="item[defaultValueKey]", :disabled="!toBoolean(item[isSystemPropertyKey])", :required="toBoolean(item[requiredKey]) && toBoolean(item[isSystemPropertyKey])", :isShowFilter="true")
            div.pt10.pl10
                button.primary.w80.sm(type="button", @click="confirm") {{$t('_ocui_dialog_confirm_words')}}
                button.ml10.w80.sm(type="button", @click="cancel") {{$t('_ocui_dialog_cancel_words')}}
                button.mr15.sm.fr(v-if="isShowConfirmAndSubmitButton", type="button", @click="confirmAndSubmit($event)") Save issues
</template>

<script>
    import TreeSelectDom from './treeSelectDom'
    import ocDialog from './js/dialog'
    import ocForm from './js/form'
    import putAside from './util/putaside'

    export default {
        name: 'oc-tagselect',
        mixins: [ TreeSelectDom ],
        props: {
            treeNode: { type: Object, default: null },
            treeDataNodes: { type: Array, default: null },
            baseProperties: { type: Array, default: null },

            filterBuIds: { type: Array, default: null },
            filterProperties: { type: Object, default: null }, //过滤属性用

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

            buKey: { type: String, default: 'bu_code' },
            propertyParentKey: { type: String, default: 'issue_category_base_property_id' },
            nodePropertyKey: { type: String, default: 'properties' },
            propertyValueKey: { type: String, default: 'property_value' },
            propertyNameKey: { type: String, default: 'property_name' },
            propertyKey: { type: String, default: 'property_key' },
            defaultValueKey: { type: String, default: 'default_value' },
            isSystemPropertyKey: { type: String, default: 'property_type' },
            requiredKey: { type: String, default: 'is_required' },
            tagDisplayKey: { type: String, default: 'tag_display'},
            isExtendValueKey: { type: String, default: 'is_extend_value'},

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

        data() {
            return {
                activePropId: null,

                samePropsLabelWidth: '80px',
                
                formPropsStyle: {
                    itemMarginRight: '10px',
                    labelMarginRight: '0'
                },

                hiddenKeys: ['bu_code', 'module_category', 'chinese_version', 'department_code'],
            }
        },

        computed: {
            selected() {
                if(this.currentValue === null || this.currentValue === undefined || this.currentValue === '') {
                    return [];
                }

                let selected = (this.currentValue instanceof Array)? this.currentValue : [this.currentValue];
                if(this.isUseProperties) {
                    return selected.map(one => (one.id || '').toString()).filter(one => !!one);
                }
                return selected.map(one => this.getString(one));
            },

            activePropName() {
                if(!this.activePropId || !this.treeDataNodes || !this.treeDataNodes.length) {
                    return '';
                }
                
                let treeNode = this.treeDataNodes.find(one => parseInt(one.id) === parseInt(this.activePropId));
                return treeNode && treeNode.name;
            },
            
            //当前激活节点的属性集合
            nodeProperties() {
                if(!this.treeDataNodes || !this.activePropId) {
                    return [];
                }

                let treeNode = this.treeDataNodes.find(one =>parseInt(one.id) === parseInt(this.activePropId));
                let nodeProperties = treeNode[this.nodePropertyKey] || [];

                return nodeProperties;
            },
            
            //当前激活节点的格式化后的属性 ----
            formatedNodeProperties() {
                var self = this;
                return this.nodeProperties.map(one => {

                    //查找出对应的根节点属性-
                    let target = this.baseProperties.find(item => item.id === one[self.propertyParentKey]);
                    if(!target || this.hiddenKeys.indexOf(target[self.propertyKey]) !== -1) {
                        //如果根节点中已经不存在了，就不显示该属性---
                        return null;
                    }
                    target = $.extend(true, {}, target);
                    let propertyValueKey = this.propertyValueKey;
                    //按照可选范围进行过滤 ----
                    let valueObj = this.getObjFromString(target[propertyValueKey]);
                    
                    //只有现设属性，才处理过滤值范围
                    if(self.toBoolean(target[self.isSystemPropertyKey])) {
                        let validValues = this.filterPropValueFromBu(one[propertyValueKey]);
                        if(Array.isArray(validValues) && validValues.length) {
                            let newValueObj = {};
                            for(let key in valueObj) {
                                if(validValues.indexOf((valueObj[key]).toString()) !== -1) {
                                    newValueObj[key] = valueObj[key];
                                }
                            }

                            valueObj = newValueObj;
                        }
                    }
                    target[self.propertyValueKey] = valueObj;
                    
                    target[self.defaultValueKey] = this.filterPropValueFromBu(one[self.defaultValueKey]);
                    
                    if(one[self.tagDisplayKey] !== null) {
                        target[self.tagDisplayKey] = one[self.tagDisplayKey];
                    }

                    //过滤掉不显示的
                    if(!target[this.tagDisplayKey]) {
                        return null;
                    }

                    return target;
                }).filter(one => !!one);
            },

            buBaseProperty() {
                if(!this.baseProperties) {
                    return null;
                }
                return this.baseProperties.find(one => one[this.propertyKey] === this.buKey);
            },

            buBasePropertyValue() {
                if(!this.buBaseProperty) {
                    return null;
                }

                return JSON.parse(this.buBaseProperty[this.propertyValueKey]);
            },

            //所有选中的节点的共同属性值---
            selectedSameProperties() {
                if(!this.currentValue || !this.treeDataNodes || !this.treeDataNodes.length) {
                    return [];
                }
                
                if(this.currentValue.length === 0) {
                    return [];
                }

                //复制跟属性---
                let validBaseProps = $.extend(true, [], this.baseProperties).filter(one => this.hiddenKeys.indexOf(one[this.propertyKey]) === -1);
                
                let curr = this.currentValue;
                if(!this.multiple) {
                    curr = [this.currentValue];
                }
                curr.map(id => {
                    let treeNode = this.treeDataNodes.find(one => parseInt(one.id) === parseInt(id));
                    if(treeNode) {
                        let nodeProperties = treeNode[this.nodePropertyKey] || [];
                        let nodePropIds = nodeProperties.map(one => parseInt(one[this.propertyParentKey]));
                        validBaseProps = validBaseProps.filter(one => nodePropIds.indexOf(one.id) !== -1);
                    }
                })
                validBaseProps.map(one => {
                    one[this.propertyValueKey] = this.formatSelectObj(one[this.propertyValueKey]);
                    return one;
                })

                return validBaseProps;
            },
            treeDataNodesMap () {
                let ret = {}
                if(this.treeDataNodes.length) {
                    this.treeDataNodes.forEach(one => {
                        ret[one.id] = one;
                    })
                }
                return ret;
            }
        },
        mounted() {
            setTimeout(_ => {
                this.appendProsDivToTree();
             }, 10);
        },

        beforeDestroy() {
            $(this.$refs.divProps).remove();
        },

        methods: {
            toBoolean(val) {
                return val === 1 || val === "1" || val === true;
            },

            beforeRemoveTreeNodeFromBody() {
                this.recyclePropsDiv();
            },

            recyclePropsDiv() {
                $(this.$refs.divProps).appendTo(this.$refs.dropContainer);
            },

            appendTreeNodeToBody() {
                if(this.currentTreeNode && this.currentTreeNode.parent()[0] !== document.body) {
                    this.currentTreeNode.appendTo(document.body).addClass('ocTreeSelectPop');
                }
                
                $(this.$refs.divProps).appendTo(this.currentTreeNode);
                this.currentTreeNode && (this.popperElm = this.currentTreeNode[0]);
            },
            
            appendProsDivToTree() {
                this.isUseProperties && $(this.$refs.divProps).appendTo(this.currentTreeNode);
            },

            //根据过滤条件，过滤一个节点，看其是否满足
            filterOneNodeByProperties(nodeModel, filterParams) {
                //节点不存在属性时，不过滤
                if(!nodeModel || !nodeModel[this.nodePropertyKey]) {
                    return false;
                }
                for(let key in filterParams) {
                    if(filterParams.hasOwnProperty(key)) {
                        let filterValue = filterParams[key];
                        if(filterValue && (typeof filterValue !== 'object' || Object.keys(filterValue).length)) {
                            if(!Array.isArray(filterValue)) { //装成数组形式
                                filterValue = [filterValue];
                            }

                            //该名称对应的baseProperty
                            let nodeBasePropertyList = this.baseProperties.filter(one => one[this.propertyKey] === key);
                            let basePropertyIdList = nodeBasePropertyList.length && nodeBasePropertyList.map(one => one.id);    
                            //该名称对应的节点属性
                            let nodeProperty = null;
                            if(basePropertyIdList && Array.isArray(basePropertyIdList)) {
                                nodeProperty = (nodeModel[this.nodePropertyKey]||[]).find(one => basePropertyIdList.includes(one[this.propertyParentKey]));
                            }
                            
                            if(!nodeProperty) {//但是节点中不存在该属性时，当做不过滤 ---
                                return false;
                            }
                            let selectNodeProperty = nodeBasePropertyList.find(one => 
                                one.id == nodeProperty[this.propertyParentKey]
                            );
                            let isExtendValue = selectNodeProperty[this.isExtendValueKey];

                            //按bu过滤，此时又没有bu选项时，直接取base的值，此时不需要过滤---  noend
                            if(isExtendValue && !this.filterBuIds) {
                                continue;
                            }

                            let validValues = null;
                            //现设属性
                            let propertyType = selectNodeProperty[this.isSystemPropertyKey];

                            if(this.toBoolean(propertyType)) {
                                validValues = this.getObjFromString(nodeProperty[this.propertyValueKey]);
                            }
                            else { //预设属性，取默认值
                                validValues = this.getObjFromString(nodeProperty[this.defaultValueKey]);
                            }

                            if(!validValues) { //空数组，空对象，null的值，直接取base的值，此时不需要过滤---
                                continue;
                            }
                            if(Object.keys(validValues).length === 0) {
                                continue;
                            }

                            if(isExtendValue) {
                                validValues = self.filterPropValueFromBu(validValues);
                            }

                            let isFindOne = filterValue.find(one => (validValues).toString().indexOf((one).toString()) !== -1);

                            if(!isFindOne) {
                                return false;
                            }
                        }
                    }
                }

                return true;
            },

            //自定义的过滤条件，优先于keyword
            filterCustomer() {
                let container = this.currentTreeNode;
                if(!container || !container.is(':visible')) {
                    return;
                }
                let filterParams = $.extend(true, {}, this.filterProperties || {});
                if(this.filterBuIds) {
                    filterParams[this.buKey] = this.filterBuIds;
                }

                

                //没有filter时，全部显示
                if(!filterParams || !Object.keys(filterParams).length) {
                    container.find('.treeItem').removeClass('firstHidden');
                    return;
                }

                let isContainsValidParams = false;
                for(let key in filterParams) {
                    if(filterParams[key] && (!Array.isArray(filterParams[key]) || filterParams[key].length !== 0)) {
                        isContainsValidParams = true;
                        break;
                    }
                }
                //都是空数组或者空值时，相当于没有过滤条件
                if(!isContainsValidParams) {
                    container.find('.treeItem').removeClass('firstHidden');

                    return;
                }

                let treeItems = container.find('.treeItem');
                treeItems.addClass('firstHidden');
                
                let treeDataNodes = this.treeDataNodes;
                var self = this;

                for(let i = 0; i< treeItems.length ;i ++) {
                    let ele = $(treeItems[i]);
                    let id = ele.attr('data-id');

                    // find方法太慢，这里观察是否有其他影响。
                    // let nodeModel = treeDataNodes.find(one => parseInt(one.id) === parseInt(id));
                    let nodeModel = this.treeDataNodesMap[id];

                    if(self.filterOneNodeByProperties(nodeModel, filterParams)) {
                        ele.removeClass('firstHidden');
                        ele.parents('.treeItem').removeClass('firstHidden');
                    }
                }
            },

            //根据可用的bu过滤属性 ----
            filterPropValueFromBu(propValueString) {
                if(!propValueString) {
                    return null;
                }

                if(propValueString.indexOf('"') === -1) {
                    return propValueString;
                }

                let validValues = [];
                try {
                    validValues = JSON.parse(propValueString);
                }
                catch(err) {
                    console.log('JSON parse error:', propValueString, err);
                }

                //bu过滤形式会有{的标准json
                if(propValueString.indexOf('{') === -1) {
                    return validValues;
                }
                
                let isArray = Array.isArray(validValues);
                if(!validValues || (isArray && !validValues.length)) {
                    return null;
                }
                
                if(this.filterBuIds) {
                    return validValues[this.filterBuIds[0]];
                }
                else if(isArray) {
                    return validValues;
                }
                return null;
            },
            
            //设置位置
            resetPosition(isResetHeight = true) {
                this.isTop = putAside(this.$refs.dropContainer, this.currentTreeNode[0], isResetHeight) > 0;
                this.isTop? this.currentTreeNode.addClass('top') : this.currentTreeNode.removeClass('top');

                this.currentTreeNode.css('height', this.currentTreeNode.css('max-height'));
            },

            afterHide() {
                this.activePropId = null;
            },

            afterShow(event) {
                if(!this.isUseProperties) {
                    return;
                }
                let target = event.target;
                if(target.classList.contains('oc-ipt-result-item')) {
                    this.activePropId = target.getAttribute('data-id');
                    let params = this.currentValue;
                    if(this.multiple) {
                        params = this.currentValue.find(one => one.id === this.activePropId);
                    } 
                    this.$nextTick(_ => {
                        ocForm.fill(this.$refs.divProps, params);
                    })
                }
                else {
                    this.activePropId = null;
                }
            },
            
            showProps(id, params) {                
                this.activePropId = id;
                //不存在属性时，不处理
                if(this.formatedNodeProperties.length) {
                    if(params) {
                        this.$nextTick(_ => {
                            ocForm.fill(divProps, params);
                        })
                    }
                }
                else {
                    this.confirm(true);
                }
            },

            confirm(notProps) {
                if(!this.activePropId) {
                    return;
                }

                let divProps = this.$refs.divProps;
                if(ocForm.validity(divProps)) {
                    let params = ocForm.getJson(divProps);
                    params.id = this.activePropId;

                    if(!this.multiple) {
                        this.currentValue = params;
                        this.hide();
                    }
                    else {
                        if(!this.currentValue) {
                            this.currentValue = [];
                        }
                        let index = this.currentValue.findIndex(one => one.id === this.activePropId);
                        if(index === -1) {
                            this.currentValue.push(params);
                        }
                        else {
                            this.currentValue.splice(index, 1, params);
                        }
                        if(!notProps) {
                            ocForm.clear(divProps);
                            this.treeNode.find('.oc-tree-select-filter input').focus();
                        }
                    }

                    this.activePropId = null;
                }
            },

            confirmAndSubmit(event) {
                this.confirm();
                this.$nextTick(_ => {
                    this.$emit('confirmAndSubmit', event, this);
                })
            },

            cancel() {
                ocForm.clear(this.$refs.divProps);
                this.activePropId = null;
                this.treeNode.find('.oc-tree-select-filter input').focus();
            },

            formatSelectObj(propertyValue) {
                let ret = {};
                if(propertyValue.indexOf('{') > -1) { //JSON字符串 ---
                    try {
                        ret = JSON.parse(propertyValue);
                        return ret;
                    }
                    catch(err) {
                        ocDialog.tips('_select 组件 ' + this.config.propertyKey + ' 数据错误', 2000);
                    }
                }

                let isObject = propertyValue.indexOf(':') > 0 || propertyValue.indexOf('：') > 0;
                let arr = propertyValue.split(/,|，|;/g);
                arr = arr.map(one => $.trim(one)).filter(one => !!one);
                if(!isObject) {
                    arr.map(one => {
                        ret[one] = one;
                    });

                    return ret;
                }
                else {
                    let ret = {};
                    arr.map(one => {
                        let objectArr = one.split(/:|：/g);
                        if(objectArr.length === 2) {
                            ret[$.trim(objectArr[0])] = $.trim(objectArr[1]);
                        }
                    })

                    return ret;
                }
            },

            remove(id) {
                if(this.multiple) {
                    let index = -1;
                    if(this.isUseProperties) {
                        index = this.currentValue.findIndex(one => one.id == id);
                    }
                    else {
                        index = this.currentValue.indexOf(id);
                    }
                    if(index !== -1) {
                        this.currentValue.splice(index, 1);
                    }
                }
                else {
                    this.currentValue = null;
                }

                this.$refs.dropContainer.focus();
            },

            addSelected(id, selectedItem) {
                if(!this.isUseProperties) {
                    if(this.multiple) {
                        if(!this.currentValue) {
                            this.currentValue = [];
                        }
                        this.currentValue.push(id);
                        //去除选中的子节点---
                        if(selectedItem) {
                            let selected = this.currentValue;
                            selectedItem.find('.treeItem').each(function(one) {
                                let childId = this.getAttribute('data-id');
                                let index = selected.indexOf(childId);
                                index !== -1 && selected.splice(index, 1);
                            })
                        }
                    }
                    else {
                        this.currentValue = id;
                        this.hide();
                    }
                }
                else {
                    this.showProps(id);
                }
            },

            getObjFromString(propertyValue) {                                                                            
                if(typeof propertyValue === 'string') {
                    if(propertyValue.indexOf('$store') === 0) {
                        try {
                            let obj = eval('this.' + propertyValue);
                            return obj || {};
                        }
                        catch(err) {
                            ocDialog.tips('_select 组件的缓存数据错误', 2000);
                            return {};
                        }
                    }
                    else {
                        let ret = {};
                        if(propertyValue.indexOf('{') > -1 || propertyValue.indexOf('[') === 0) { //JSON字符串 ---
                            try {
                                ret = JSON.parse(propertyValue);
                                return ret;
                            }
                            catch(err) {
                                ocDialog.tips('_select 组件 ' + this.config.propertyKey + ' 数据错误', 2000);
                            }
                        }
                        
                        let isObject = propertyValue.indexOf(':') > 0 || propertyValue.indexOf('：') > 0;
                        let arr = propertyValue.split(/,|，/g);
                        arr = arr.map(one => $.trim(one)).filter(one => !!one);
                        if(!isObject) {
                            return arr;
                        }
                        else {
                            let ret = {};
                            arr.map(one => {
                                let objectArr = one.split(/:|：/g);
                                if(objectArr.length === 2) {
                                    ret[$.trim(objectArr[0])] = $.trim(objectArr[1]);
                                }
                            })

                            return ret;
                        }
                    }
                }

                return propertyValue;  
            }
        }
    }
</script>


<style lang="stylus" scoped>
    .divProsItemLabel
        color inherit
        font-size inherit
        position relative
    .divPropsContainer
        position absolute
        left 0
        top 0 
        width 100%
        height 100%
        background rgba(255, 255, 255, .9) 
        border solid 1px #ddd
        overflow auto
        span.must
            position relative
            &:before
                position absolute
                content "*"
                color red
                left 0
                font-weight bold
</style>

