<template>
  <div class="el-table" :data-fixed="fixedColumns.length" :data-rightFixed="rightFixedColumns.length"
    :class="[{
      'el-table--fixed': fixedColumns.length + rightFixedColumns.length > 0,
      'el-table--fit': fit,
      'el-table--striped': stripe,
      'el-table--border': border || isGroup,
      'el-table--hidden': isHidden,
      'el-table--group': isGroup,
      'el-table--fluid-height': maxHeight,
      'el-table--enable-row-hover': !store.states.isComplex,
      'el-table--enable-row-transition': (store.states.data || []).length !== 0 && (store.states.data || []).length < 100
    }, tableSize ? `el-table--${ tableSize }` : '']"
    @mouseleave="handleMouseLeave($event)">
    <div class="hidden-columns" ref="hiddenColumns"><slot></slot></div>
    <div class="el-table__header-wrapper" ref="headerWrapper"
      v-if="showHeader"
      :style="[
       { width: scrollbarAvailable && columns.length ? bodyWidth : '' }
       ]">
      <table-header
        ref="tableHeader"
        :store="store"
        :layout="layout"
        :border="border"
        :default-sort="defaultSort"
        :style="{ width: layout.bodyWidth ? layout.bodyWidth + 'px' : '' }">
      </table-header>
    </div>
    <div
      class="el-table__body-wrapper"
      ref="bodyWrapper"
      :class="[`is-scroll-${scrollPosition}`, {'table-no-data': !data || data.length === 0}]"
      @mouseover="hoverBodyCloumn"
      @scroll="handleScroll"
      :style="[
        bodyHeight,
        {overflowX: scrollbarAvailable ? 'hidden' : ''},
        {overflowY: scrollbarColAvailable && cloneBodyHeight && wrapperHeight > cloneBodyHeight ? 'scroll' : ''}
      ]">
      <table-body
        class="table-body"
        ref="tableContent"
        :context="context"
        :store="store"
        :stripe="stripe"
        :layout="layout"
        :row-class-name="rowClassName"
        :row-style="rowStyle"
        :highlight="highlightCurrentRow"
        :style="{ width: bodyWidth }">
      </table-body>
      <div :data-width="bodyWidth" class="el-table__empty-block" v-if="!data || data.length === 0">
        <span class="el-table__empty-text"><slot name="empty">{{ emptyText || t('el.table.emptyText') }}</slot></span>
      </div>
      <div class="el-table__append-wrapper" ref="appendWrapper" v-if="$slots.append">
        <slot name="append"></slot>
      </div>
      <!-- {{scrollbarAvailable}}##{{wrapperWidth}}##{{bodyWidth}} -->
      <div class="table-drag-panel"
        v-show="scrollbarAvailable && wrapperWidth && wrapperWidth < parseInt(bodyWidth)"
        :class="[{
          'active': params.flag
        }]"
        ref="dragPanel">
      </div>
    </div>
    <!-- 模拟浏览器 -->
    <!-- ******{{scrollbarColAvailable}}*{{cloneBodyHeight}}****{{cloneWrapperHeight}}***{{cloneBodyHeight}} -->
    <div class="table-drag-cloumn-panel-wrapper">
      <div class="table-drag-cloumn-panel"
        v-show="scrollbarColAvailable && cloneBodyHeight && cloneWrapperHeight > cloneBodyHeight"
        :class="[{
          'active': colParams.flag
        }]"
        ref="dragCloumnPanel">
      </div>
    </div>
    <div class="el-table__footer-wrapper" ref="footerWrapper" v-if="showSummary" v-show="data && data.length > 0">
      <table-footer
        ref="tableFooterContent"
        :store="store"
        :layout="layout"
        :border="border"
        :sum-text="sumText || t('el.table.sumText')"
        :summary-method="summaryMethod"
        :default-sort="defaultSort"
        :style="{ width: layout.bodyWidth ? layout.bodyWidth + 'px' : '' }">
      </table-footer>
    </div>
    <div class="el-table__fixed" ref="fixedWrapper"
      v-if="fixedColumns.length > 0"
      @mouseover="hoverBodyCloumn"
      :style="[
        { width: layout.fixedWidth ? layout.fixedWidth + 'px' : '' },
        {overflow: scrollbarAvailable ? 'hidden' : ''},
        fixedHeight
      ]">
      <div class="el-table__fixed-header-wrapper" ref="fixedHeaderWrapper" v-if="showHeader">
        <table-header
          ref="fixedTableHeader"
          fixed="left"
          :border="border"
          :store="store"
          :layout="layout"
          :style="{ width: layout.fixedWidth ? layout.fixedWidth + 'px' : '' }"></table-header>
      </div>
      <div
        class="el-table__fixed-body-wrapper"
        ref="fixedBodyWrapper"
        :style="[
          { top: layout.headerHeight + 'px' },
          fixedBodyHeight
        ]">
        <table-body
          fixed="left"
          ref="tableFixedContent"
          :store="store"
          :stripe="stripe"
          :layout="layout"
          :highlight="highlightCurrentRow"
          :row-class-name="rowClassName"
          :row-style="rowStyle"
          :style="{ width: layout.fixedWidth ? layout.fixedWidth + 'px' : '' }">
        </table-body>
        <div class="el-table__append-gutter" :style="{ height: layout.appendHeight + 'px' }" v-if="$slots.append"></div>
      </div>
      <div class="el-table__fixed-footer-wrapper" ref="fixedFooterWrapper" v-if="showSummary" v-show="data && data.length > 0">
        <table-footer
          fixed="left"
          :border="border"
          :sum-text="sumText || t('el.table.sumText')"
          :summary-method="summaryMethod"
          :store="store"
          :layout="layout"
          :style="{ width: layout.fixedWidth ? layout.fixedWidth + 'px' : '' }"></table-footer>
      </div>
    </div>
    <div class="el-table__fixed-right" ref="rightFixedWrapper"
      v-if="rightFixedColumns.length > 0"
      @mouseover="hoverBodyCloumn"
      :style="[
        { width: layout.rightFixedWidth ? layout.rightFixedWidth + 'px' : '' },
        { right: layout.scrollY ? (border ? (0 + 'px') : '') : '' },
        fixedHeight
      ]">
      <!-- 8 => layout.gutterWidth
      TODO
      right: layout.scrollY ? (border ? layout.gutterWidth  : (layout.gutterWidth  || 0)) + 'px' : ''
      -->
      <div class="el-table__fixed-header-wrapper" ref="rightFixedHeaderWrapper" v-if="showHeader">
        <table-header
          ref="rightFixedTableHeader"
          fixed="right"
          :border="border"
          :store="store"
          :layout="layout"
          :style="{ width: layout.rightFixedWidth ? layout.rightFixedWidth + 'px' : '' }"></table-header>
      </div>
      <!--  { 'margin-right': -layout.gutterWidth + 'px'},-->
      <div class="el-table__fixed-body-wrapper" ref="rightFixedBodyWrapper"
        :style="[
          { top: layout.headerHeight + 'px' },
          fixedBodyHeight
        ]">
        <table-body
          ref="tableFixedRight"
          fixed="right"
          :store="store"
          :stripe="stripe"
          :layout="layout"
          :row-class-name="rowClassName"
          :row-style="rowStyle"
          :highlight="highlightCurrentRow"
          :style="{ width: layout.rightFixedWidth ? layout.rightFixedWidth + 'px' : '' }">
        </table-body>
      </div>
      <div class="el-table__fixed-footer-wrapper" ref="rightFixedFooterWrapper" v-if="showSummary" v-show="data && data.length > 0">
        <table-footer
          fixed="right"
          :border="border"
          :sum-text="sumText || t('el.table.sumText')"
          :summary-method="summaryMethod"
          :store="store"
          :layout="layout"
          :style="{ width: layout.rightFixedWidth ? layout.rightFixedWidth + 'px' : '' }"></table-footer>
      </div>
    </div>
    <div class="el-table__fixed-right-patch"
      v-if="rightFixedColumns.length > 0"
      :style="{ width: layout.scrollY ? layout.gutterWidth + 'px' : '0', height: layout.headerHeight + 'px' }"></div><!-- 0 => layout.gutterWidth-->
    <div class="el-table__column-resize-proxy" ref="resizeProxy" v-show="resizeProxyVisible"></div>
  </div>
</template>

<script type="text/babel">
  import ElCheckbox from 'element-ui/packages/checkbox';
  import throttle from 'throttle-debounce/throttle';
  import debounce from 'throttle-debounce/debounce';
  import { addResizeListener, removeResizeListener } from 'element-ui/src/utils/resize-event';
  import Locale from 'element-ui/src/mixins/locale';
  import Migrating from 'element-ui/src/mixins/migrating';
  import TableStore from './table-store';
  import TableLayout from './table-layout';
  import TableBody from './table-body';
  import TableHeader from './table-header';
  import TableFooter from './table-footer';
  import { mousewheel} from './util';
  import { getScrollbarSpec } from 'element-ui/src/utils/util';

  const getCss = (o, key) => {
    return o.currentStyle
      ? o.currentStyle[key]
      : document.defaultView.getComputedStyle(o, false)[key];
  };

  let tableIdSeed = 1;

  export default {
    name: 'ElTable',

    mixins: [Locale, Migrating],

    props: {
      data: {
        type: Array,
        default: function() {
          return [];
        }
      },

      size: String,

      width: [String, Number],

      height: [String, Number],

      maxHeight: [String, Number],

      fit: {
        type: Boolean,
        default: true
      },

      stripe: Boolean,

      border: Boolean,

      rowKey: [String, Function],

      context: {},

      showHeader: {
        type: Boolean,
        default: true
      },

      showSummary: Boolean,

      sumText: String,

      summaryMethod: Function,

      rowClassName: [String, Function],

      rowStyle: [Object, Function],

      cellClassName: [String, Function],

      cellStyle: [Object, Function],

      headerRowClassName: [String, Function],

      headerRowStyle: [Object, Function],

      headerCellClassName: [String, Function],

      headerCellStyle: [Object, Function],

      highlightCurrentRow: Boolean,

      currentRowKey: [String, Number],

      emptyText: String,

      expandRowKeys: Array,

      defaultExpandAll: Boolean,

      defaultSort: Object,

      tooltipEffect: String,

      spanMethod: Function,

      forceScrollbars: {
        type: Boolean,
        default: false
      },
      autoResizeScroll: {
        type: Boolean,
        default: false
      }
    },

    components: {
      TableHeader,
      TableFooter,
      TableBody,
      ElCheckbox
    },

    provide() {
      return {
        rootTable: this
      };
    },

    methods: {
      getMigratingConfig() {
        return {
          events: {
            expand: 'expand is renamed to expand-change'
          }
        };
      },

      setCurrentRow(row) {
        this.store.commit('setCurrentRow', row);
      },

      toggleRowSelection(row, selected) {
        this.store.toggleRowSelection(row, selected);
        this.store.updateAllSelected();
      },

      toggleRowExpansion(row, expanded) {
        this.store.toggleRowExpansion(row, expanded);
      },

      clearSelection() {
        this.store.clearSelection();
      },

      clearFilter() {
        this.store.clearFilter();
      },

      clearSort() {
        this.store.clearSort();
      },

      handleMouseLeave() {
        this.store.commit('setHoverRow', null);
        if (this.hoverState) this.hoverState = null;

        if (this.$refs.dragCloumnPanel) {
          this.$refs.dragCloumnPanel.style.opacity = 0;
        }
      },

      updateScrollY() {
        this.layout.updateScrollY();
      },

      bindEvents() {
        const { headerWrapper, footerWrapper } = this.$refs;
        const refs = this.$refs;
        let self = this;
        this.bodyWrapper.addEventListener('scroll', function() {
          if (headerWrapper) headerWrapper.scrollLeft = this.scrollLeft;
          if (footerWrapper) footerWrapper.scrollLeft = this.scrollLeft;
          if (refs.fixedBodyWrapper) refs.fixedBodyWrapper.scrollTop = this.scrollTop;
          if (refs.rightFixedBodyWrapper) refs.rightFixedBodyWrapper.scrollTop = this.scrollTop;
          const maxScrollLeftPosition = this.scrollWidth - this.offsetWidth - 1;
          const scrollLeft = this.scrollLeft;
          if (scrollLeft >= maxScrollLeftPosition) {
            self.scrollPosition = 'right';
          } else if (scrollLeft === 0) {
            self.scrollPosition = 'left';
          } else {
            self.scrollPosition = 'middle';
          }
        });

        const scrollBodyWrapper = event => {
          const { deltaX, deltaY } = event;

          if (Math.abs(deltaX) < Math.abs(deltaY)) return;

          if (deltaX > 0) {
            this.bodyWrapper.scrollLeft += 10;
          } else if (deltaX < 0) {
            this.bodyWrapper.scrollLeft -= 10;
          }
        };
        if (headerWrapper) {
          mousewheel(headerWrapper, throttle(16, scrollBodyWrapper));
        }
        if (footerWrapper) {
          mousewheel(footerWrapper, throttle(16, scrollBodyWrapper));
        }

        if (this.fit) {
          this.windowResizeListener = throttle(50, () => {
            if (this.$ready) this.doLayout();
          });
          addResizeListener(this.$el, this.windowResizeListener);
        }
      },

      doLayout() {
        this.store.updateColumns();
        this.updateScrollY();
        this.layout.update();
        this.$nextTick(() => {
          if (this.height) {
            this.layout.setHeight(this.height);
          } else if (this.maxHeight) {
            this.layout.setMaxHeight(this.maxHeight);
          } else if (this.shouldUpdateHeight) {
            this.layout.updateHeight();
          }
          if (this.$el) {
            this.isHidden = this.$el.clientWidth === 0;
            if (this.isHidden && this.layout.bodyWidth) {
              setTimeout(() => this.doLayout());
            }
          }
        });
      },
      hoverBodyCloumn() {
        if (this.$refs.dragCloumnPanel) {
          if (this.$refs.tableContent.$el.offsetHeight > this.cloneBodyHeight && this.cloneBodyHeight) {
            this.$refs.dragCloumnPanel.style.opacity = 1;
            this.$refs.dragCloumnPanel.style.display = 'block';
          }
        }
      },
      leaveBodyCloumn() {
        if (this.$refs.dragCloumnPanel) {
          this.$refs.dragCloumnPanel.style.opacity = 0;
          this.$refs.dragCloumnPanel.style.display = 'none';
        }
      },
      onScroll(refs, scrollTop) {
        let wrapBar = this.$refs.dragCloumnPanel;
        let wrapHBar = this.$refs.dragPanel;
        let tableHeight = this.$refs.tableContent.$el.offsetHeight;
        this.wrapperHeight = this.$refs.bodyWrapper.offsetHeight;
        let disY = this.wrapperHeight * scrollTop / (tableHeight + this.layout.headerHeight + this.layout.footerHeight);
        wrapBar.style.top = disY + 'px';
        wrapHBar.style.transform = `translateY(${scrollTop}px)`;
      },
      handleScroll(bodyWrapper) {
        let scrollTop = this.$refs.bodyWrapper.scrollTop;
        this.onScroll(bodyWrapper, scrollTop);
      },

      startCloumDrag() {
        let bar = this.$refs.dragCloumnPanel;
        let target = this.$refs.dragCloumnPanel;
        let wrap = this.$refs.bodyWrapper;
        let barOffsetTop = target.offsetTop;
        const mousemoveHandler = event => {
          let e = event || window.event;
          if (this.colParams.flag) {
            target.style.transition = 'initial';
            let nowY = e.clientY;
            let disY = nowY - this.colParams.currentY;
            let offset = barOffsetTop + disY;

            let allHeight = this.wrapperHeight + this.layout.headerHeight + this.layout.footerHeight;
            let barHeight = allHeight * bar.style.height.split('%')[0] / 100;
            let tableHeight = this.$refs.tableContent.$el.offsetHeight;

            if (offset <= -this.layout.headerHeight) {
              offset = -this.layout.headerHeight;
            }
            if (offset >= (this.wrapperHeight - barHeight)) {
              offset = this.wrapperHeight - barHeight;
            }
            let scrollTop = 0;
            if (offset !== 0) {
              scrollTop = (offset * (tableHeight + this.layout.headerHeight)) / this.wrapperHeight;
            }
            wrap.scrollTop = scrollTop;
            if (event.preventDefault) {
              event.preventDefault();
            }
            return false;
          }
        };
        bar.onmousedown = event => {
          // 记录滚动高度
          barOffsetTop = target.offsetTop;
          document.addEventListener('mousemove', mousemoveHandler);
          document.addEventListener('mouseup', mouseupHandler);
          this.colParams.flag = true;
          this.wrapperHeight = this.$refs.bodyWrapper.offsetHeight;
          if (!event) {
            event = window.event;
            bar.onselectstart = () => {
              return false;
            };
          }
          let e = event;
          this.colParams.currentX = e.clientX;
          this.colParams.currentY = e.clientY;
        };

        // 鼠标弹起
        const mouseupHandler = () => {
          barOffsetTop = target.offsetTop;
          document.removeEventListener('mousemove', mousemoveHandler);
          document.removeEventListener('mouseup', mouseupHandler);
          this.colParams.flag = false;
          target.style.transition = '';
          if (getCss(target, 'right') !== 'auto') {
            this.colParams.right = getCss(target, 'right');
          }
          if (getCss(target, 'top') !== 'auto') {
            this.colParams.top = getCss(target, 'top');
          }
        };
      },

      startDrag() {
        let bar = this.$refs.dragPanel;
        let target = this.$refs.dragPanel;
        if (getCss(target, 'left') !== 'auto') {
          this.params.left = getCss(target, 'left');
        }
        if (getCss(target, 'top') !== 'auto') {
          this.params.top = getCss(target, 'top');
        }

        // 速表移动
        const mousemoveHandler = event => {
          let e = event || window.event;
          if (this.params.flag) {
            target.style.transition = 'initial';
            let nowX = e.clientX;
            // let nowY = e.clientY
            let disX = nowX - this.params.currentX;
            // let disY = nowY - this.params.currentY
            let offset = window.parseInt(this.params.left) + disX;
            if (offset <= 0) {
              offset = 0;
            }
            let bw = this.wrapperWidth / 2;
            if (offset >= bw) {
              offset = bw;
            }
            let tableWidth = this.$refs.tableContent.$el.offsetWidth;
            let percent = (tableWidth - this.wrapperWidth) / bw;
            target.style.left = offset + 'px';
            // target.style.top = parseInt(params.top) + disY + "px";
            this.$refs.tableContent.$el.style.transform = `translateX(${-offset * percent}px)`;
            this.$refs.headerWrapper.style.transform = `translateX(${-offset * percent}px)`;
            this.$refs.tableFooterContent && (this.$refs.tableFooterContent.$el.style.transform = `translateX(${-offset * percent}px)`);
            if (event.preventDefault) {
              event.preventDefault();
            }
            return false;
          }
        };

        // 鼠标按下
        bar.onmousedown = event => {
          document.addEventListener('mousemove', mousemoveHandler);
          document.addEventListener('mouseup', mouseupHandler);
          this.params.flag = true;
          this.wrapperWidth = this.$refs.bodyWrapper.offsetWidth;
          if (!event) {
            event = window.event;
            bar.onselectstart = () => {
              return false;
            };
          }
          let e = event;
          this.params.currentX = e.clientX;
          this.params.currentY = e.clientY;
        };

        // 鼠标弹起
        const mouseupHandler = () => {
          document.removeEventListener('mousemove', mousemoveHandler);
          document.removeEventListener('mouseup', mouseupHandler);
          this.params.flag = false;
          target.style.transition = '';
          if (getCss(target, 'left') !== 'auto') {
            this.params.left = getCss(target, 'left');
          }
          if (getCss(target, 'top') !== 'auto') {
            this.params.top = getCss(target, 'top');
          }
        };
      },
      initBarHeight() {
        let bar = this.$refs.dragCloumnPanel;
        if (bar && this.layout.bodyHeight) {
          let a = this.layout.bodyHeight;
          // 计算滚动条高度
          if (this.$refs.tableContent.$el) {
            bar.style.height = `${a * 100 / (this.$refs.tableContent.$el.offsetHeight + this.layout.headerHeight + this.layout.footerHeight)}%`;
            // 滚动条的父级是包含header和footer， 所以初始化的位置应该有一个header的高度
            bar.style.transform = `translateY(${this.layout.headerHeight}px)`;
          }
        }
      }
    },

    created() {
      this.scrollbarSpec = getScrollbarSpec().width;
      this.scrollbarColSpec = getScrollbarSpec().height;
      this.scrollbarAvailable = this.scrollbarSpec > 0 || this.forceScrollbars;
      this.scrollbarColAvailable = this.scrollbarColSpec >= 0 || this.forceScrollbars;
      this.tableId = 'el-table_' + tableIdSeed + '_';
      this.debouncedLayout = debounce(50, () => this.doLayout());
      this.$nextTick(() => {
        this.cloneWrapperHeight = this.$refs.tableContent.$el.offsetHeight;
        this.wrapperWidth = this.$refs.bodyWrapper.offsetWidth - 17; // this.layout.gutterWidth;
        this.wrapperHeight = this.$refs.bodyWrapper.offsetHeight;
        if (this.scrollbarAvailable) {
          this.wrapperWidth = this.$refs.bodyWrapper.offsetWidth;
        }
        if (this.scrollbarAvailable && this.wrapperWidth && this.wrapperWidth < window.parseInt(this.bodyWidth)) {

          this.startDrag();
          if (this.autoResizeScroll) {
            // 注册resize事件
            // 目前采用的是百分比计算，所以浏览器窗口大小改变不对table的scroll计算产生影响
            // 之后如果有强制resize需求可以开放这部分
            this.winResize = () => {
              this.wrapperWidth = this.$refs.bodyWrapper.offsetWidth;
            };
            window.addEventListener('resize', this.winResize);
          }
        }
        if (this.height) {
          if (this.scrollbarColAvailable && this.wrapperHeight && this.cloneWrapperHeight + this.layout.headerHeight > window.parseInt(this.height)) {
            this.startCloumDrag();
            if (this.autoResizeScroll) {
              this.winResize = () => {
                this.wrapperWidth = this.$refs.bodyWrapper.offsetWidth;
                this.wrapperHeight = this.$refs.bodyWrapper.offsetHeight;
              };
              window.addEventListener('resize', this.winResize);
            }
          }
        }
        if (this.maxHeight) {
          if (this.scrollbarColAvailable && this.wrapperHeight && this.cloneWrapperHeight + this.layout.headerHeight > window.parseInt(this.maxHeight)) {
            this.startCloumDrag();
            if (this.autoResizeScroll) {
              this.winResize = () => {
                this.wrapperWidth = this.$refs.bodyWrapper.offsetWidth;
                this.wrapperHeight = this.$refs.bodyWrapper.offsetHeight;
              };
              window.addEventListener('resize', this.winResize);
            }
          }
        }
      });
    },

    computed: {
      tableSize() {
        return this.size || (this.$ELEMENT || {}).size;
      },

      bodyWrapper() {
        return this.$refs.bodyWrapper;
      },

      shouldUpdateHeight() {
        return typeof this.height === 'number' ||
          this.fixedColumns.length > 0 ||
          this.rightFixedColumns.length > 0;
      },

      selection() {
        return this.store.states.selection;
      },

      columns() {
        return this.store.states.columns;
      },

      tableData() {
        return this.store.states.data;
      },

      fixedColumns() {
        return this.store.states.fixedColumns;
      },

      rightFixedColumns() {
        return this.store.states.rightFixedColumns;
      },

      bodyHeight() {
        let style = {};
        if (this.height) {
          style = {
            height: this.layout.bodyHeight ? this.layout.bodyHeight + 'px' : '',
            'margin-right': `${-17}px`, // this.layout.bodyHeight ? `${-this.layout.gutterWidth}px` : 0
            width: this.layout.bodyHeight ? 'auto' : '100%'
          };
        } else if (this.maxHeight) {
          style = {
            'max-height': (this.showHeader
              ? this.maxHeight - this.layout.headerHeight - this.layout.footerHeight
              : this.maxHeight - this.layout.footerHeight) + 'px',
            'margin-right': `${-17}px`,
            width: this.showHeader ? 'auto' : '100%'
          };
        }
        return style;
      },

      bodyWidth() {
        const { bodyWidth, scrollY, gutterWidth } = this.layout; // scrollY, gutterWidth
        return bodyWidth ? bodyWidth - (scrollY ? gutterWidth : 0) + 'px' : '';
      },

      fixedBodyHeight() {
        let style = {};

        if (this.height) {
          style = {
            height: this.layout.fixedBodyHeight ? this.layout.fixedBodyHeight + 'px' : ''
          };
        } else if (this.maxHeight) {
          let maxHeight = this.maxHeight;

          if (this.showHeader) {
            maxHeight -= this.layout.headerHeight;
          }

          maxHeight -= this.layout.footerHeight;

          style = {
            'max-height': maxHeight + 'px'
          };
        }

        return style;
      },

      fixedHeight() {
        let style = {};
        if (this.maxHeight) {
          style = {
            bottom: (this.layout.scrollX && this.data.length) ? 0 + 'px' : '' // 0 => this.layout.gutterWidth
          };
        } else {
          style = {
            height: this.layout.viewportHeight ? this.layout.viewportHeight + 'px' : ''
          };
        }
        return style;
      }
    },

    watch: {
      height(value) {
        this.initBarHeight();
        this.layout.setHeight(value);
      },

      maxHeight(value) {
        this.layout.setMaxHeight(value);
      },

      currentRowKey(newVal) {
        this.store.setCurrentRowKey(newVal);
      },

      bodyWidth(val) {
        if (this.scrollbarAvailable && val && this.wrapperWidth && this.wrapperWidth < window.parseInt(val)) {
          this.startDrag();
        }
      },
      wrapperWidth(v) {
        this.wrapperWidth = this.$refs.bodyWrapper.offsetWidth;
      },

      bodyHeight(val) {
        if (val.height || val['max-height']) {
          this.cloneBodyHeight = val.height ? val.height.split('px')[0] : (val['max-height'] ? val['max-height'].split('px')[0] : null);
        }
        if (this.height) {
          if (this.scrollbarColAvailable &&
            val.height &&
            this.wrapperHeight &&
            this.wrapperHeight <
            window.parseInt(val.height)
          ) {
            this.startCloumDrag();
          }
        }
        if (this.maxHeight) {
          if (
            this.scrollbarColAvailable &&
            val['max-height'] &&
            this.wrapperHeight &&
            this.wrapperHeight <
            window.parseInt(this.maxHeight)
          ) {
            this.startCloumDrag();
          }
        }
      },

      data: {
        immediate: true,
        handler(val) {
          this.store.commit('setData', val);
          if (this.$ready) this.doLayout();
          this.$nextTick(() => {
            this.initBarHeight();
            this.startCloumDrag();
            this.$refs.bodyWrapper.scrollTop = 0;
          });
        }
      },

      expandRowKeys: {
        immediate: true,
        handler(newVal) {
          if (newVal) {
            this.store.setExpandRowKeys(newVal);
          }
        }
      }
    },

    destroyed() {
      if (this.windowResizeListener) removeResizeListener(this.$el, this.windowResizeListener);
      if (this.winResize) window.removeEventListener('resize', this.winResize);
    },

    mounted() {
      this.bindEvents();
      this.doLayout();
      // init filters
      this.store.states.columns.forEach(column => {
        if (column.filteredValue && column.filteredValue.length) {
          this.store.commit('filterChange', {
            column,
            values: column.filteredValue,
            silent: true
          });
        }
      });

      this.$ready = true;
      this.$nextTick(() => {
        this.initBarHeight();
      });

    },

    data() {
      const store = new TableStore(this, {
        rowKey: this.rowKey,
        defaultExpandAll: this.defaultExpandAll
      });
      const layout = new TableLayout({
        store,
        table: this,
        fit: this.fit,
        showHeader: this.showHeader
      });
      return {
        store,
        layout,
        isHidden: false,
        renderExpanded: null,
        resizeProxyVisible: false,
        // 是否拥有多级表头
        isGroup: false,
        scrollPosition: 'left',
        scrollbarSpec: 0,
        scrollbarAvailable: false,
        wrapperWidth: 'auto',
        cloneBodyHeight: null,
        params: {
          left: 0,
          top: 0,
          currentX: 0,
          currentY: 0,
          flag: false
        },
        scrollbarColSpec: 0,
        scrollbarColAvailable: false,
        wrapperHeight: 'auto',
        cloneWrapperHeight: '',
        colParams: {
          right: 0,
          top: 0,
          currentX: 0,
          currentY: 0,
          flag: false
        }
      };
    }
  };
</script>
