import { scrollTop } from '../../utils/assist';
import {deepCopy} from '../../utils/assist';
let common = {};
function Table_getSelection () {
     // 分别拿根数据和子数据的已选项
     let selectionIndexes = [];
     let selectionRowKeys = [];
     for (let i in this.objData) {
         const objData = this.objData[i];
         if (objData._isChecked) selectionIndexes.push(parseInt(i));
         if (objData.children && objData.children.length) {
             selectionRowKeys = selectionRowKeys.concat(this.getSelectionChildrenRowKeys(objData, selectionRowKeys));
         }
     }

     // 去重的 RowKeys
     selectionRowKeys = [...new Set(selectionRowKeys)];

     let selection = [];

     this.data.forEach((item, index) => {
         if (selectionIndexes.indexOf(index) > -1) {
             // 自定义:加行号索引 便于批量删除
             item._customIndex = index;
             
             selection = selection.concat(item);
         }
         if (item.children && item.children.length && selectionRowKeys.length) {
             selection = selection.concat(this.getSelectionChildren(item, selection, selectionRowKeys));
         }
     });

     selection = [...new Set(selection)];
     return JSON.parse(JSON.stringify(selection));
}

function Table_handleResize () {
    //let tableWidth = parseInt(getStyle(this.$el, 'width')) - 1;
// 原代码当列宽不设置的时 会出现缩进的现象
//let tableWidth = this.$el.offsetWidth - 1;
//自定义
let tableWidth = this.$el.parentNode.offsetWidth;
let columnsWidth = {};
let sumMinWidth = 0;
let hasWidthColumns = [];
let noWidthColumns = [];
let maxWidthColumns = [];
let noMaxWidthColumns = [];
this.cloneColumns.forEach((col) => {
    if (col.width) {
        hasWidthColumns.push(col);
    }
    else{
        noWidthColumns.push(col);
        if (col.minWidth) {
            sumMinWidth += col.minWidth;
        }
        if (col.maxWidth) {
            maxWidthColumns.push(col);
        }
        else {
            noMaxWidthColumns.push(col);
        }
    }
    col._width = null;
});

let unUsableWidth = hasWidthColumns.map(cell => cell.width).reduce((a, b) => a + b, 0);
let usableWidth = tableWidth - unUsableWidth - sumMinWidth - (this.showVerticalScrollBar?this.scrollBarWidth:0) - 1;
let usableLength = noWidthColumns.length;
let columnWidth = 0;
if(usableWidth > 0 && usableLength > 0){
    columnWidth = parseInt(usableWidth / usableLength);
}

for (let i = 0; i < this.cloneColumns.length; i++) {
    const column = this.cloneColumns[i];
    let width = columnWidth + (column.minWidth?column.minWidth:0);
    if(column.width){
        width = column.width;
    }
    else{
        if (column._width) {
            width = column._width;
        }
        else {
            if (column.minWidth > width){
                width = column.minWidth;
            }
            else if (column.maxWidth < width){
                width = column.maxWidth;
            }

            if (usableWidth>0) {
                usableWidth -= width - (column.minWidth?column.minWidth:0);
                usableLength--;
                if (usableLength > 0) {
                    columnWidth = parseInt(usableWidth / usableLength);
                }
                else {
                    columnWidth = 0;
                }
            }
            else{
                columnWidth = 0;
            }
        }
    }

    column._width = width;

    columnsWidth[column._index] = {
        width: width
    };

}
if(usableWidth>0) {
    usableLength = noMaxWidthColumns.length;
    columnWidth = parseInt(usableWidth / usableLength);
    for (let i = 0; i < noMaxWidthColumns.length; i++) {
        const column = noMaxWidthColumns[i];
        let width = column._width + columnWidth;
        if (usableLength > 1) {
            usableLength--;
            usableWidth -= columnWidth;
            columnWidth = parseInt(usableWidth / usableLength);
        }
        else {
            columnWidth = 0;
        }

        column._width = width;

        columnsWidth[column._index] = {
            width: width
        };

    }
}

this.tableWidth = this.cloneColumns.map(cell => cell._width).reduce((a, b) => a + b, 0) + (this.showVerticalScrollBar?this.scrollBarWidth:0) + 1;
this.columnsWidth = columnsWidth;
this.fixedHeader();
}

function Table_highlightCurrentRow (_index, rowKey) {
    const objData = rowKey ? this.getDataByRowKey(rowKey) : this.objData[_index];
    if (!objData) return;
    if (!this.highlightRow || objData._isHighlight) return;
    this.handleCurrentRow('highlight', _index, rowKey);
}

function getRandomStr (len = 32) {
    const $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
    const maxPos = $chars.length;
    let str = '';
    for (let i = 0; i < len; i++) {
        str += $chars.charAt(Math.floor(Math.random() * maxPos));
    }
    return str;
};

function Table_makeColumnsId (columns) {
    const cloneColumns = deepCopy(columns);
    return cloneColumns.map(item => {
        if ('children' in item) item.children = this.makeColumnsId(item.children);
        item.__id = getRandomStr(6);
        return item;
    });
};

function TableHead_scrollBarCellClass(){
    let hasRightFixed = false;
    for(let i in this.headRows){
        for(let j in this.headRows[i]){
            if(this.headRows[i][j].fixed === 'right') {
                hasRightFixed=true;
                break;
            }
            if(hasRightFixed) break;
        }
    }
    return [
        {
            [`${this.prefixCls}-hidden`]: hasRightFixed,
            'efuture-table-scroll-th':true
        }
    ];
}

function handleCheckClick (event, new_window = false) {
    if (this.to) {
        if (this.target === '_blank') {
            return false;
        } else {
            event.preventDefault();
            if (this.to === 'click') {
                this.$emit('click', event);
            } else {
                this.handleClick(new_window);
            }
        }
    }
}
function Upload_handleClick () {
    if (this.itemDisabled) return;
      // 自定义：弹框之前check
      if (this.$parent && this.$parent.onClick) {
        this.$parent.onClick()
      } else {
        if (this.$refs.input) {
            this.$refs.input.click();
        }
      }
}

function DatePicker_reset() {
    if (this.$refs.pickerPanel && this.$refs.pickerPanel.reset) {
        this.$refs.pickerPanel.reset();
    }
}

function DatePicker_handleKeydown (e) {
    const pickerPrefixCls = 'ivu-picker';
    const keyCode = e.keyCode;

    // handle "tab" key
    if (keyCode === 9) {
        if (this.visible) {
            e.stopPropagation();
            e.preventDefault();

            if (this.isConfirm) {
                const selector = `.${pickerPrefixCls}-confirm > *`;
                const tabbable = this.$refs.drop.$el.querySelectorAll(selector);
                this.internalFocus = true;
                const element = [...tabbable][e.shiftKey ? 'pop' : 'shift']();
                element.focus();
            } else {
                this.handleClose();
            }
        } else {
            this.focused = false;
        }
    }

    // open the panel
    const arrows = [37, 38, 39, 40];
    if (!this.visible && arrows.includes(keyCode)) {
        this.visible = true;
        return;
    }

    // close on "esc" key
    if (keyCode === 27) {
        if (this.visible) {
            e.stopPropagation();
            this.handleClose();
        }
    }

    // select date, "Enter" key
    if (keyCode === 13) {
        const timePickers = this.timeSpinnerList.map(item => item.timeSpinner);
        if (timePickers.length > 0) {
            const columnsPerPicker = timePickers[0].showSeconds ? 3 : 2;
            const pickerIndex = Math.floor(this.focusedTime.column / columnsPerPicker);
            const value = this.focusedTime.time[pickerIndex];

            timePickers[pickerIndex].chooseValue(value);
            return;
        }

        if (this.type.match(/range/)) {
            this.$refs.pickerPanel.handleRangePick(this.focusedDate, 'date');
        } else {
            const panels = this.panelTableList.map(item => item.panelTable);
            const compareDate = (d) => {
                const sliceIndex = ['year', 'month', 'date'].indexOf((this.type)) + 1;
                return [d.getFullYear(), d.getMonth(), d.getDate()].slice(0, sliceIndex).join('-');
            };
           
            const dateIsValid = panels.find(({ cells }) => {
                return cells.find(({ date, disabled }) => compareDate(date) === compareDate(this.focusedDate) && !disabled);
            });
            if (dateIsValid) {
                if (this.modelValue === null) {
                    this.onPick(null, false, 'date');
                } else {
                    this.onPick(this.focusedDate, false, 'date');
                }
            }
        }
    }

    if (!arrows.includes(keyCode)) return; // ignore rest of keys

    // navigate times and dates
    if (this.focusedTime.active) e.preventDefault(); // to prevent cursor from moving
    this.navigateDatePanel(keyValueMapper[keyCode], e.shiftKey);
}

function DatePicker_handleBlur(e) {
    if (this.internalFocus) {
        this.internalFocus = false;
        return;
    }
    if (this.visible) {
        e.preventDefault();
        return;
    }

    this.isFocused = false;
    this.onSelectionModeChange(this.type);
    this.internalValue = this.internalValue.slice(); // trigger panel watchers to reset views
    this.reset();
    if (this.$refs.pickerPanel) {
        this.$refs.pickerPanel.onToggleVisibility(false);
    }
}
export const isClient = typeof window !== 'undefined';

function getScroll(target, top) {
    const prop = top ? 'pageYOffset' : 'pageXOffset';
    const method = top ? 'scrollTop' : 'scrollLeft';

    let ret = target[prop];

    if (isClient && typeof ret !== 'number') {
        ret = window.document.documentElement[method];
    }

    return ret;
}

function getOffset(element) {
    if (!isClient) return;
    const rect = element.getBoundingClientRect();

    const scrollTop = getScroll(window, true);
    const scrollLeft = getScroll(window);

    const docEl = window.document.body;
    const clientTop = docEl.clientTop || 0;
    const clientLeft = docEl.clientLeft || 0;

    return {
        top: rect.top + scrollTop - clientTop,
        left: rect.left + scrollLeft - clientLeft
    };
}

function Anchor_handleScroll (e) {
    this.upperFirstTitle = !!this.titlesOffsetArr[0] && e.target.scrollTop < this.titlesOffsetArr[0].offset;
    if (this.animating) return;
    // this.updateTitleOffset();
    const scrollTop = this.scrollContainer.scrollTop;
    this.getCurrentScrollAtTitleId(scrollTop);
}

function Affix_handleScroll () {
    if (!isClient) return;
    const affix = this.affix;
    const scrollTop = getScroll(window, true);
    const elOffset = getOffset(this.$el);
    const windowHeight = window.innerHeight;
    const elHeight = this.$el.getElementsByTagName('div')[0].offsetHeight;

    // Fixed Top
    if ((elOffset.top - this.offsetTop) < scrollTop && this.offsetType == 'top' && !affix) {
        this.affix = true;
        this.slotStyle = {
            width: this.$refs.point.clientWidth + 'px',
            height: this.$refs.point.clientHeight + 'px'
        };
        this.slot = true;
        this.styles = {
            top: `${this.offsetTop}px`,
        };
        if (elOffset.left) {
            this.styles.left =  `${elOffset.left}px`;
        }
        if (this.$el.offsetWidth) {
            this.styles.width =  `${this.$el.offsetWidth}px`;
        }
        this.$emit('on-change', true);
    } else if ((elOffset.top - this.offsetTop) > scrollTop && this.offsetType == 'top' && affix) {
        this.slot = false;
        this.slotStyle = {};
        this.affix = false;
        this.styles = null;

        this.$emit('on-change', false);
    }

    // Fixed Bottom
    if ((elOffset.top + this.offsetBottom + elHeight) > (scrollTop + windowHeight) && this.offsetType == 'bottom' && !affix) {
        this.affix = true;
        this.styles = {
            bottom: `${this.offsetBottom}px`,
            left: `${elOffset.left}px`,
            width: `${this.$el.offsetWidth}px`
        };

        this.$emit('on-change', true);
    } else if ((elOffset.top + this.offsetBottom + elHeight) < (scrollTop + windowHeight) && this.offsetType == 'bottom' && affix) {
        this.affix = false;
        this.styles = null;

        this.$emit('on-change', false);
    }
}
common.initTable = function (obj) {
    obj.methods.getSelection  = Table_getSelection;
    obj.methods.handleResize  = Table_handleResize;
    obj.methods.highlightCurrentRow = Table_highlightCurrentRow;
    obj.methods.makeColumnsId = Table_makeColumnsId;
    obj.components.tableHead.methods.scrollBarCellClass = TableHead_scrollBarCellClass;
}

common.initBreadcrumbItem = function (obj) {
    obj.mixins[0].methods.handleCheckClick  = handleCheckClick;
}
common.initButton = function (obj) {
    obj.mixins[0].methods.handleCheckClick  = handleCheckClick;
}
common.initCard = function (obj) {
    obj.mixins[0].methods.handleCheckClick  = handleCheckClick;
}
common.initCell = function (obj) {
    obj.mixins[0].methods.handleCheckClick  = handleCheckClick;
}
common.initMenuItem = function (obj) {
    obj.mixins[1].methods.handleCheckClick  = handleCheckClick;
}
common.initUpload = function (obj) {
    obj.methods.handleClick  = Upload_handleClick;
}
common.initDatePicker = function (obj) {
    obj.mixins[0].methods.reset  = DatePicker_reset;
    obj.mixins[0].methods.handleBlur  = DatePicker_handleBlur;
    obj.mixins[0].methods.handleKeydown  = DatePicker_handleKeydown;
}

common.initAffix = function (obj) {
    obj.methods.handleScroll  = Affix_handleScroll;
}
common.initAnchor = function (obj) {
    obj.methods.handleScroll  = Anchor_handleScroll;
}
common.initEview = function (ViewUI) {
    common.initTable(ViewUI.Table);
    common.initBreadcrumbItem(ViewUI.BreadcrumbItem);
    common.initButton(ViewUI.Button);
    common.initCard(ViewUI.Card);
    common.initCell(ViewUI.Cell);
    common.initMenuItem(ViewUI.MenuItem);
    common.initUpload(ViewUI.Upload);
    common.initDatePicker(ViewUI.DatePicker);
    common.initAffix(ViewUI.Affix);
    common.initAnchor(ViewUI.Anchor);
}
export default common;