import createFooting from './createFooting.jsx';
import ColumnManager from './ColumnManager.js';
import clone from 'lodash/clone';
const defaultRowHeight = 39.34;
const THRESHOLD = 20;
function debounce(callback, delay) {
  let timerId;

  return function () {
    let context = this;
    let args = arguments;

    if (timerId) {
      window.cancelAnimationFrame(timerId);
    }

    timerId = window.requestAnimationFrame(function () {
      callback.apply(context, args);
    }, delay);
  };
}

export default function (Vue) {
  let vcTable = clone(require('ant-design-vue/es/vc-table/src/Table.js').default);
  vcTable.data = (function (fn) {
    return function () {
      if (this.tableType == 't-table') {
        this.initRun = false;
        this.direction = 'right';
        this.beforeScrollLeft = 0;
        this.translateY = 0;

        return {
          ...fn.apply(this, arguments),
          columnManager: new ColumnManager(this.columns, this),
          centreColumns: null,
        };
      } else {
        return fn.apply(this, arguments);
      }
    };
  })(vcTable.data);
  vcTable.computed = {
    vsColumn({ centreColumns, columnManager, columns }) {
      if (centreColumns && columnManager) {
        let leftColumns = columnManager.leftColumns(),
          rightColumns = columnManager.rightColumns();
        centreColumns[0].firstTd = true;
        centreColumns[centreColumns.length - 1].lastTd = true;
        return [...leftColumns, ...centreColumns, ...rightColumns];
      }
      return columns;
    },
  };

  vcTable.methods.init = function (config) {
    this.initRun = true;
    for (let key in config) {
      this.columnManager[key] = config[key];
    }
    let leftColumns = this.columnManager.leftColumns();
    this.ref_tableFixed = this.ref_bodyTable.querySelector('table');
    const columns = this.columns;

    if (this.vScrollX?.enabled) {
      let warpWidth = 0,
        a = [];
      let i = 0,
        leng = columns.length;
      for (i; i < leng; i++) {
        let { width } = columns[i];
        warpWidth += width;
        a.push(warpWidth);
        if (warpWidth > this.ref_bodyTable.offsetWidth) {
          this.columnManager.x_start = leftColumns.length;
          this.columnManager.x_end = i + leftColumns.length + 1;
          this.centreColumns = columns.slice(leftColumns.length, this.columnManager.x_end);
          return false;
        }
      }
    } else {
      let rightColumns = this.columnManager.rightColumns();
      this.centreColumns = columns.slice(leftColumns.length, columns.length - rightColumns.length);
    }
  };
  vcTable.methods.renderEmptyText = (function (fn) {
    return function () {
      const vNode = fn.apply(this, arguments);
      if (this.tableType == 't-table' && vNode && this.scroll?.y) {
        vNode.data.style = {
          height: this.scroll.y + 'px',
        };
      }

      return vNode;
    };
  })(vcTable.methods.renderEmptyText);

  vcTable.methods.renderMainTable = (function (fn) {
    return function () {
      if (this.tableType == 't-table') {
        var h = this.$createElement;
        const { scroll, prefixCls, vsColumn, columnManager } = this;
        const isAnyColumnsFixed = columnManager.isAnyColumnsFixed();
        const scrollable = isAnyColumnsFixed || scroll.x || scroll.y;

        const table = [
          this.renderTable({
            // store:this.store,
            columns: vsColumn,
            isAnyColumnsFixed,
          }),
          this.renderEmptyText(),
          this.renderFooter(),
        ];

        return scrollable ? <div class={`${prefixCls}-scroll`}>{table}</div> : table;
      } else {
        return fn.apply(this, arguments);
      }
    };
  })(vcTable.methods.renderMainTable);

  vcTable.methods.renderTable = (function (fn) {
    return function (options) {
      if (this.tableType == 't-table' && this.centreColumns) {
        options.columns = this.vsColumn;
      }
      return fn.apply(this, [options]);
    };
  })(vcTable.methods.renderTable);

  //给空容器一个高
  vcTable.methods.renderEmptyText = (function (fn) {
    return function (h) {
      const vNode = fn.apply(this, arguments);
      const { minHeight } = this.scroll;
      if (vNode && minHeight) {
        vNode.data.style = {
          minHeight: isNaN(minHeight) ? minHeight : minHeight + 'px',
          display: 'flex',
          justifyContent: 'center',
          alignItems: 'center',
        };
      }

      return vNode;
    };
  })(vcTable.methods.renderEmptyText);
  vcTable.inject = {
    tableType: {
      default: 'tableType',
    },
  };
  vcTable.props.attachFooter = {
    type: null,
  };

  vcTable.props.vScrollX = {
    type: Object,
  };
  vcTable.props.vScrollY = {
    type: Object,
  };

  vcTable.props.verticalState = {
    type: null,
  };
  vcTable.props.tData = {
    type: Array,
  };
  vcTable.props.virtualScrollLength = {
    type: Number,
  };

  vcTable.props.defaultCountKey = {
    type: null,
  };

  delete vcTable.props.getBodyWrapper;

  vcTable.methods.createFooting = createFooting;

  vcTable.methods.renderFooter = function () {
    let f = null;

    var h = this.$createElement;
    var footer = this.footer,
      prefixCls = this.prefixCls,
      data = this.tData || this.data;
    if (this.tableType == 't-table') {
      let attachFooter = null;
      if (this.attachFooter) {
        attachFooter = this.createFooting(data);
      }
      return footer ? h('div', { class: prefixCls + '-footer', key: 'footer' }, [attachFooter, footer(data)]) : attachFooter;
    } else {
      return footer ? h('div', { class: prefixCls + '-footer', key: 'footer' }, [footer(data)]) : f;
    }
  };

  vcTable.methods.renderTable = (function (fn) {
    return function () {
      if (this.tableType == 't-table') {
        arguments[0].isAnyColumnsFixed = false;
        arguments[0].fixed = undefined;
      }
      const vNode = fn.apply(this, arguments);
      if (this.tableType == 't-table'&&this.showHeader) {
        console.log('renderTable');
        //行脱拽时的显示的虚线
        vNode.unshift(this._c('div', {
          class: 't-table-drag-line',
          style: { display: 'none' }
        }));
      }
      return vNode;
    };
  })(vcTable.methods.renderTable);

  vcTable.methods.bodyRowsHeight = function () {
    let tr = this.ref_bodyTable.querySelector('tbody.ant-table-tbody>tr');
    if (tr) {
      this.bodyRowsHeight = () => {
        return tr.getBoundingClientRect().height || 39;;
      };
      return this.bodyRowsHeight()
    } else {
      return null;
    }
  };
  /** 纵向滚动 */
  vcTable.methods.updateVisibleRows = function (event) {
    var isVisible = false;
    let { target } = event;
    if (this.vScrollY?.enabled) {
      let { vScrollY, ref_attachFooter, verticalState } = this;
      let { rowCount, rowHeight } = verticalState;
      if (!rowCount) return;
      let virtualScrollLength = vScrollY.oSize;
      const tDataLan = this.tData.length;

      this.translateY = target.scrollTop;

      let { scrollHeight, scrollTop } = target;
      let startIndex, endIndex;
      const { start, end } = this.verticalState;
      const deltaY = this.beforeScrollTop ? scrollTop - this.beforeScrollTop : scrollTop;
      console.log(start, end);
      console.log('scrollHeight='+target.scrollHeight)

      if (deltaY > 0) {

        isVisible = true;
        startIndex = ~~(scrollTop / rowHeight);
        endIndex = virtualScrollLength + startIndex;

        if (endIndex >= tDataLan) {
          startIndex = tDataLan - virtualScrollLength;
          endIndex = tDataLan;
          this.translateY = scrollHeight - virtualScrollLength * rowHeight;
        }

        console.log('rowCount='+rowCount,"startIndex="+startIndex,'endIndex='+endIndex,'start='+start,'end='+end);


        if (startIndex == start || end == endIndex) {
        } else if (startIndex - start >= rowCount || endIndex >= tDataLan) {
          this.$emit('verticalState', { start: startIndex, end: endIndex, translateY: this.translateY });
        }
      } else if (deltaY < 0) {
        isVisible = true;

        let st = ~~((scrollHeight - scrollTop) / rowHeight) - rowCount;
        startIndex = tDataLan - virtualScrollLength - st;
        endIndex = startIndex + virtualScrollLength;

        if (startIndex <= 0) {
          startIndex = 0;
          endIndex = virtualScrollLength;
        }

        console.log('rowCount='+rowCount,"startIndex="+startIndex,'endIndex='+endIndex,'start='+start,'end='+end);

        if (startIndex == start || end == endIndex) {
        } else if (end - endIndex >= rowCount || startIndex <= 0) {
          this.translateY = scrollTop - (virtualScrollLength - rowCount) * rowHeight;
          if (this.translateY <= 0) {
            this.translateY = 0;
          }

          this.$emit('verticalState', { start: startIndex, end: endIndex, translateY: this.translateY });
        }
      }

      virtualScrollLength = scrollHeight = scrollTop = startIndex = endIndex = rowCount = rowHeight = verticalState = ref_attachFooter = void 0;
    }
    this.beforeScrollTop = target.scrollTop;

    return isVisible
  };

  /** 横向向滚动 */
  function rightAnimate(target, right_ruler) {
    let scrollLeft = target.scrollLeft;
    let tableFixed = this.ref_tableFixed;
    right_ruler = right_ruler ? right_ruler : this.columnManager.translateX + tableFixed.offsetWidth - target.offsetWidth - scrollLeft;
    let leftColumns = this.columnManager.leftColumns(),
      rightColumns = this.columnManager.rightColumns();
    let num = 30;

    const { columns } = this;
    let length = columns.length - rightColumns.length;
    if (right_ruler <= num) {
      let { x_end } = this.columnManager;
      let x_start = leftColumns.length;
      let x_widht = 0;
      let col = columns[x_start];

      try {
        while (col) {
          x_widht += col.width;
          if (x_widht < scrollLeft) {
            x_start++;
            col = columns[x_start];
            this.columnManager.translateX = x_widht;
          } else {
            col = false;
          }
        }

        x_end = x_end >= length ? length : x_end + 1;
        x_widht = right_ruler;
        col = columns[x_end];

        while (col) {
          x_widht += col.width;
          if (x_widht < 0) {
            x_end = x_end >= length ? length : x_end + 1;
            col = columns[x_end];
          } else {
            col = false;
          }
        }
      } catch (err) {
        new Error(err);
      }
      this.centreColumns = columns.slice(x_start, x_end);
      // function animation() {

      //   requestAnimationFrame(animation);
      // }

      // requestAnimationFrame(animation);

      this.columnManager.x_end = x_end;
      this.columnManager.x_start = x_start;
      this.direction = 'right';
      console.log(this.direction);
      scrollLeft = col = right_ruler = rightColumns = rightColumns = void 0;
    }
  }

  function leftAnimate(target, left_ruler) {
    let { columns, translateX, scrollWidth } = this.columnManager;
    let ref_bodyTable = this.ref_bodyTable;
    let tableFixed = this.ref_tableFixed;

    let scrollLeft = target.scrollLeft;
    let scrollRight = scrollWidth - scrollLeft;
    left_ruler = left_ruler ? left_ruler : scrollWidth - translateX - scrollRight;
    let leftColumns = this.columnManager.leftColumns(),
      rightColumns = this.columnManager.rightColumns();
    let num = 30;
    leftColumns.forEach((columns) => {
      num += columns.width;
    });
    let r_length = columns.length - rightColumns.length;
    let l_length = leftColumns.length;
    let { x_start, x_end } = this.columnManager;

    if (left_ruler <= num) {
      x_start = Math.max(x_start - 1, l_length);
      let col = columns[x_start];
      let x_widht = left_ruler;
      try {
        while (col) {
          x_widht += col.width;
          if (x_widht < 0) {
            x_start = Math.max(x_start - 1, l_length);
            col = columns[x_start];
          } else {
            col = false;
          }
        }

        this.columnManager.translateX = Math.max(scrollLeft - x_widht, 0);

        let rightWidht = 0;
        // x_end = r_length;
        col = columns[x_end - 1];
        scrollRight = tableFixed.offsetWidth - ref_bodyTable.offsetWidth;
        while (col) {
          rightWidht += col.width;
          if (rightWidht < scrollRight) {
            x_end--;
            col = columns[x_end];
          } else {
            col = false;
          }
        }

        x_end = Math.min(x_end, r_length);
      } catch (err) {
        new Error(err);
      }

      this.centreColumns = columns.slice(x_start, x_end);
      this.columnManager.x_end = x_end;
      this.columnManager.x_start = x_start;
      this.direction = 'left';
      console.log(this.direction);

      rightColumns = scrollRight = x_widht = ref_bodyTable = scrollLeft = col = left_ruler = leftColumns = void 0;
    }
  }

  function updateHorizontalCell(event) {
    const { target } = event;
    const { ref_headTable, ref_attachFooter } = this;

    const { scrollLeft } = target;
    if (this.vScrollX?.enabled) {
      //
      const deltaX = scrollLeft - this.beforeScrollLeft;

      let node = document.createTextNode('');
      let ob = new MutationObserver((mutationsList, observer) => {
        if (deltaX > 0) {
          this.rightAnimate(target, null);
        } else if (deltaX < 0) {
          this.leftAnimate(target);
        }
        observer.disconnect();
        node = null;
        ob = null;
      });
      ob.observe(node, { characterData: true });
      node.data = '1';
    }

    // const deltaX = scrollLeft - this.beforeScrollLeft;
    // if (deltaX > 0) {
    //   this.rightAnimate(target, null);
    // } else if (deltaX < 0) {
    //   this.leftAnimate(target);
    // }

    if (ref_headTable?.scrollLeft !== scrollLeft) {
      ref_headTable.scrollLeft = scrollLeft;
    }
    if (ref_attachFooter) {
      let el = ref_attachFooter.$el;
      el.scrollLeft = scrollLeft;
    }
    this.beforeScrollLeft = scrollLeft;
  }

  var ticking = false;
  vcTable.methods.vsBodyScroll = function (event) {
    if (!ticking) {
      window.requestAnimationFrame(() => {
        let isVisible = this.updateVisibleRows(event);
        !isVisible&& this.updateHorizontalCell(event);
        ticking = false;
      });
      ticking = true;
    }
  };

  vcTable.deactivated = function () {
    if (this.tableType == 't-table') {
      this.ref_bodyTable.removeEventListener('scroll', this.vsBodyScroll);
    }
  };
  vcTable.mounted = (function (fn) {
    return function () {
      fn.apply(this, arguments);
      if (this.tableType == 't-table') {
        this.ref_bodyTable.addEventListener('scroll', this.vsBodyScroll, {
          passive: true,
        });
      }
    };
  })(vcTable.mounted);

  // 比较函数
  function compareArrays(key, arr1, arr2) {
    if (arr1.length !== arr2.length) {
      return false;
    }

    for (let i = 0; i < arr1.length; i++) {
      const obj1 = arr1[i];
      const obj2 = arr2[i];
      // 比较关键字段
      if (obj1[key] !== obj2[key]) {
        return false;
      }
    }
    return true;
  }

  vcTable.created = function () {
    if (this.tableType == 't-table') {
      this.rightAnimate = debounce(rightAnimate, 400);
      //  this.rightAnimate = rightAnimate;
      this.leftAnimate = debounce(leftAnimate, 400);
      //this.leftAnimate = leftAnimate;
      this.updateHorizontalCell = updateHorizontalCell;
      this.$watch('columns', (value, oldValue) => {
        let result = compareArrays('width', value, oldValue);
        console.log('columns11111', result, value.length, oldValue.length);
        if (!result) {
          this.columnManager = new ColumnManager(value, this);
          this.centreColumns = null;

          this.$nextTick(() => {
            this.initRun = false;
          });
        }
      });

      this.syncFixedTableRowHeight = () => {
        if (!this.initRun && this.tData.length > 0 && this.ref_bodyTable) {
          this.scroll.x = this.ref_bodyTable.getBoundingClientRect().width;
          console.log('init');
          //横向初始化scroll.y
          this.init({
            translateX: 0,
            scrollWidth: this.ref_bodyTable.scrollWidth,
            width: this.scroll.x,
            scrollTarget: this.ref_bodyTable,
          });
        }
      };
      this.setScrollPositionClassName = function () {};
      this.renderLeftFixedTable = function () {
        return null;
      };
      this.renderRightFixedTable = function () {
        return null;
      };
    }
    if (this.vScrollY?.enabled) {
      this.rowCount = 0;
      this.rowHeight = -1;
    }
  };

  function defaultYState() {
    return {
      start: 0,
      end: THRESHOLD,
      translateY: 0,
      bodyScrollHeight: -1,
      rowCount: void 0,
      rowHeight: defaultRowHeight,
    };
  }

  // function useDefer(maxCount = 4, frameCount) {
  //   let rafId;
  //   function updateFrameCount() {
  //     rafId = requestAnimationFrame(() => {
  //       frameCount.value++;
  //       if (frameCount.value >= maxCount) {
  //         return;
  //       }
  //       updateFrameCount();
  //     });
  //   }
  //   updateFrameCount();
  //   //销毁
  //   return {
  //     defer: function (n) {
  //       return frameCount.value >= n;
  //     },
  //     onUnmounted: function () {
  //       cancelAnimationFrame(rafId);
  //     }
  //   };
  // }
  require('ant-design-vue/es/vc-table/src/Table.js').default = {
    // functional: true,
    name: 'midst',
    inject: vcTable.inject,
    props: vcTable.props,
    data() {
      // this.useDefer = useDefer();

      return {
        YState: defaultYState(),
      };
    },

    watch: {
      '$props.data': {
        // enabled: false,
        // gt: 40,
        // oSize: 20,
        // rows: 10
        handler: function (value, oldValue=[]) {
          if (value.length > 0 && this.vScrollY) {
            let YState = defaultYState();
            this.$nextTick(() => {
              if (!YState.rowHeight) {
                let rowHeight = this?.bodyRowsHeight?.();
                YState.rowHeight = rowHeight;
              }

              const { rows, oSize, gt } = this.vScrollY;
              this.YState.bodyScrollHeight = value.length * YState.rowHeight;
              this.YState.rowCount = rows;
              if (value.length!==oldValue.length&& value.length <oSize) {
                this.YState.translateY=0
              }

            })

          } else {
            this.YState = defaultYState();
          }
        },
        immediate: true,
      },
    },
    computed: {
      ref_bodyTable() {
        return this.$refs.midst.ref_bodyTable;
      },
      tableNode() {
        return this.$refs.midst.tableNode;
      },
      isScrollY() {
        const { data, vScrollY } = this;
        if (data.length < 50) {
          return false;
        } else if (!vScrollY || !vScrollY.enabled) {
          return false;
        } else {
          return true;
        }
      },
    },
    methods: {
      getBodyTable() {
        return this.$refs.midst.getBodyTable();
      },
      bodyRowsHeight() {
        return this.$refs.midst?.bodyRowsHeight?.();
      },
    },

    render(h) {
      const { $listeners, pagination, scopedSlots, slots, tableType } = this;
      if (tableType !== 't-table') {
        return h(vcTable, {
          ref: 'midst',
          props: this.$props,
          on: $listeners,
          scopedSlots,
          slots,
        });
      }

      let { data, ...props } = this.$props;
      const tData = data;
      props.tData = tData;
      props.data = tData.slice(0);

      if (this.isScrollY) {
        const { start, end } = this.YState;
        props.data = tData.slice(start, end);

        $listeners.verticalState = (state, rowHeight) => {
          // this.$emit('loading', true);
          if (state) {
            for (let key in state) {
              this.YState[key] = state[key];
            }
            // this.YState = {
            //   ...this.YState,
            //   ...state
            // };
          }
        };
      } else {
        this.YState.bodyScrollHeight = -1;
        props.tData = props.data = data;
      }
      props.verticalState = this.YState;
      // props.isScrollRun = this.isScrollY;

      const vcTableConfig = {
        ref: 'midst',
        props,
        on: $listeners,
        scopedSlots,
        slots,
      };

      const vNode = h(vcTable, vcTableConfig);

      return vNode
    },
  };

  vcTable.render= (function (fn) {
    return function (h) {


      const vNode = fn.apply(this, arguments);
      return vNode
    }
  })(vcTable.render);
}
