<script>
    import List from './list.vue';
    import Operation from './operation.vue';
    import Locale from '../../mixins/locale';
    import Emitter from '../../mixins/emitter';
    import { deepCopy } from '../../utils/assist';

    const prefixCls = 'ivu-transfer';

    export default {
        mixins: [ Emitter, Locale ],
        render (createElement) {

            function cloneVNode (vnode) {
                const clonedChildren = vnode.children && vnode.children.map(vnode => cloneVNode(vnode));
                const cloned = createElement(vnode.tag, vnode.data, clonedChildren);
                cloned.text = vnode.text;
                cloned.isComment = vnode.isComment;
                cloned.componentOptions = vnode.componentOptions;
                cloned.elm = vnode.elm;
                cloned.context = vnode.context;
                cloned.ns = vnode.ns;
                cloned.isStatic = vnode.isStatic;
                cloned.key = vnode.key;

                return cloned;
            }

            const vNodes = this.$slots.default === undefined ? [] : this.$slots.default;
            const clonedVNodes = this.$slots.default === undefined ? [] : vNodes.map(vnode => cloneVNode(vnode));

            return createElement('div', {
                'class': this.classes
            }, [
                createElement('List', {
                    ref: 'left',
                    props: {
                        prefixCls: this.prefixCls + '-list',
                        data: this.leftData,
                        leftTree:this.leftTree,
                        checkHidden:this.checkHidden,
                        renderFormat: this.renderFormat,
                        checkedKeys: this.leftCheckedKeys,
                        validKeysCount: this.leftValidKeysCount,
                        lstyle: this.listStyle,
                        title: this.localeTitles[0],
                        filterable: this.filterable,
                        filterPlaceholder: this.localeFilterPlaceholder,
                        filterMethod: this.filterMethod,
                        notFoundText: this.localeNotFoundText
                    },
                    on: {
                        'on-checked-keys-change': this.handleLeftCheckedKeysChange
                    }
                }, vNodes),

                createElement('Operation', {
                    props: {
                        prefixCls: this.prefixCls,
                        operations: this.operations,
                        leftActive: this.leftValidKeysCount > 0,
                        rightActive: this.rightValidKeysCount > 0
                    }
                }),

                createElement('List', {
                    ref: 'right',
                    props: {
                        prefixCls: this.prefixCls + '-list',
                        data: this.rightData,
                        leftTree:false,
                        checkHidden:this.checkHidden,
                        renderFormat: this.renderFormat,
                        checkedKeys: this.rightCheckedKeys,
                        validKeysCount: this.rightValidKeysCount,
                        lstyle: this.listStyle,
                        title: this.localeTitles[1],
                        filterable: this.filterable,
                        filterPlaceholder: this.localeFilterPlaceholder,
                        filterMethod: this.filterMethod,
                        notFoundText: this.localeNotFoundText
                    },
                    on: {
                        'on-checked-keys-change': this.handleRightCheckedKeysChange
                    }
                }, clonedVNodes)
            ]);
        },

        components: { List, Operation },
        props: {
            data: {
                type: Array,
                default () {
                    return [];
                }
            },
            fields:{
                type:Array,
                default(){
                    return []
                }
            },
            leftTree:{
                type:Boolean,
                default:false
            },
            checkHidden:{
                type:Boolean,
                default:false
            },
            renderFormat: {
                type: Function,
                default (item) {
                    return item.label || item.key;
                }
            },
            targetKeys: {
                type: Array,
                default () {
                    return [];
                }
            },
            selectedKeys: {
                type: Array,
                default () {
                    return [];
                }
            },
            listStyle: {
                type: Object,
                default () {
                    return {};
                }
            },
            titles: {
                type: Array
            },
            operations: {
                type: Array,
                default () {
                    return [];
                }
            },
            filterable: {
                type: Boolean,
                default: false
            },
            filterPlaceholder: {
                type: String
            },
            filterMethod: {
                type: Function,
                default (data, query) {
                    const type = ('label' in data) ? 'label' : 'key';
                    return data[type].indexOf(query) > -1;
                }
            },
            notFoundText: {
                type: String
            }
        },
        data () {
            return {
                prefixCls: prefixCls,
                leftData: [],
                rightData: [],
                leftCheckedKeys: [],
                rightCheckedKeys: []
            };
        },
        computed: {
            classes () {
                return [
                    `${prefixCls}`
                ];
            },
            leftValidKeysCount () {
                return this.getValidKeys('left').length;
            },
            rightValidKeysCount () {
                return this.getValidKeys('right').length;
            },
            localeFilterPlaceholder () {
                if (this.filterPlaceholder === undefined) {
                    return this.t('i.transfer.filterPlaceholder');
                } else {
                    return this.filterPlaceholder;
                }
            },
            localeNotFoundText () {
                if (this.notFoundText === undefined) {
                    return this.t('i.transfer.notFoundText');
                } else {
                    return this.notFoundText;
                }
            },
            localeTitles () {
                if (this.titles === undefined) {
                    return [this.t('i.transfer.titles.source'), this.t('i.transfer.titles.target')];
                } else {
                    return this.titles;
                }
            }
        },
        methods: {
            getValidKeys (direction) {
               return this[`${direction}Data`].filter(data => !(data.disabled!=undefined?data.disabled:false) && this[`${direction}CheckedKeys`].indexOf(data.key) > -1).map(data => data.key);
            },
            foreachCloneData:function (oData,returnData) {
                let newRow;
                let vChild;
                for(let row=0;row<oData.length;row++){
                    if(oData[row].child==undefined||oData[row].child==null||oData[row].child.length==0){
                        oData[row].hasChild=false;
                        oData[row].expand=false;
                        newRow = deepCopy(oData[row]);// todo 直接替换
                        returnData[parseInt(this.vCopyLenth)] = newRow;
                        this.vCopyLenth=parseInt(this.vCopyLenth)+1;
                    }else{
                        vChild=oData[row].child;
                        oData[row].hasChild=true;
                        oData[row].expand=false;
                        newRow = deepCopy(oData[row]);// todo 直接替换
                        returnData[parseInt(this.vCopyLenth)] = newRow;
                        this.vCopyLenth=parseInt(this.vCopyLenth)+1;
                        this.foreachCloneData(vChild,returnData)
                    }
                }
            },
            foreachCloneDataLevel:function(oData,firstID,level,parentTrId){
                if(oData!==undefined&&oData!=null){
                    level=parseInt(level)+1;
                    for(let row=0;row<oData.length;row++){
                        for(let i=0;i<this.fields.length;i++){
                            if(oData[row][this.fields[i].field]!=undefined){
                                oData[row][this.fields[i].map]=oData[row][this.fields[i].field];
                                oData[row][this.fields[i].field]=null;
                            }
                        }
                        oData[row].level=level;
                        oData[row].firstR="li_Root_"+firstID;
                        oData[row].parentTr="li_"+parentTrId+"_"+oData[row].pId;
                        this.foreachCloneDataLevel(oData[row].child,firstID,level,oData[row].pId)
                    }
                }
            },
            makeCloneData(){
                let data = [];
                this.vCopyLenth=0;
                let level=0;
                let oData=JSON.parse(JSON.stringify(this.data));
                for(let row=0;row<oData.length;row++){
                    for(let i=0;i<this.fields.length;i++){
                        if(oData[row][this.fields[i].field]!=undefined){
                            oData[row][this.fields[i].map]=oData[row][this.fields[i].field];
                            oData[row][this.fields[i].field]=null;
                        }
                    }
                    oData[row].firstR="li_Root_"+oData[0].key;
                    oData[row].level=0;
                    oData[row].parentTr="Root"
                    this.foreachCloneDataLevel(oData[row].child,oData[0].key,0,"Root")
                }
                this.foreachCloneData(oData,data);
                return data;
            },
            splitData (init = false) {
                if(this.leftTree==true){
                    this.leftData =this.makeCloneData();
                }else{
                    this.leftData = [...this.data];
                }
                this.rightData = [];
                if (this.targetKeys.length > 0) {
                    this.targetKeys.forEach((targetKey) => {
                        this.rightData.push(
                                this.leftData.filter((data, index) => {
                                    if (data.key === targetKey) {
                                        if(this.leftTree){
                                            let obj = document.getElementById("li_" + data.pId + "_" + data.key);
                                            if(obj!=undefined&&obj!=null){
                                                this.addClass(obj, "remove-hidden")
                                            }
                                        }
                                        else{
                                            this.leftData.splice(index, 1);
                                        }
                                        return true;
                                    }
                                    return false;
                                })[0]);
                    });
                }
                if (init) {
                    this.splitSelectedKey();
                }
            },
            hasClass:function (obj,cls) {
                return obj.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'));
            },
            addClass:function (obj,cls) {
                if (!this.hasClass(obj, cls)) obj.className += " " + cls;
            },
            removeClass:function (obj,cls) {
                if (this.hasClass(obj, cls)) {
                    var reg = new RegExp('(\\s|^)' + cls + '(\\s|$)');
                    obj.className = obj.className.replace(reg, ' ');
                }
            },
            splitSelectedKey () {
                const selectedKeys = this.selectedKeys;
                if (selectedKeys.length > 0) {
                    this.leftCheckedKeys = this.leftData
                            .filter(data => selectedKeys.indexOf(data.key) > -1)
                            .map(data => data.key);
                    this.rightCheckedKeys = this.rightData
                            .filter(data => selectedKeys.indexOf(data.key) > -1)
                            .map(data => data.key);
                }
            },
            moveTo (direction) {
                const targetKeys = this.targetKeys;
                const opposite = direction === 'left' ? 'right' : 'left';
                const moveKeys = this.getValidKeys(opposite);
                const newTargetKeys = direction === 'right' ?
                        moveKeys.concat(targetKeys) :
                        targetKeys.filter(targetKey => !moveKeys.some(checkedKey => targetKey === checkedKey));

                this.$refs[opposite].toggleSelectAll(false);
                this.$emit('on-change', newTargetKeys, direction, moveKeys);
                if(this.leftTree &&direction=='left'){
                    this.targetKeys.forEach((targetKey) => {
                        this.leftData.filter((data, index) => {
                            if (data.key === targetKey) {
                                if(!data.hasChild&&data.pId!=null&&data.pId!=""){
                                   let row = document.getElementById("li_" + data.pId + "_" + data.key);
                                    if(row!=undefined){
                                        if (this.hasClass(row, "remove-hidden")) {
                                            this.removeClass(row, "remove-hidden");
                                        }
                                    }
                                }
                            }
                        })
                    })
                }
                this.dispatch('FormItem', 'on-form-change', {
                    tarketKeys: newTargetKeys,
                    direction: direction,
                    moveKeys: moveKeys
                });
            },
            handleLeftCheckedKeysChange (keys) {
                this.leftCheckedKeys = keys;
            },
            handleRightCheckedKeysChange (keys) {
                this.rightCheckedKeys = keys;
            }
        },
        watch: {
            targetKeys () {
                this.splitData(false);
            },
            data () {
                this.splitData(false);
            }
        },
        created () {
            this.splitData(true);
        }
    };
</script>
