import { defineComponent, ref, computed, provide, toRef, watch, nextTick, createVNode, mergeProps, TransitionGroup } from 'vue';
import _objectWithoutProperties from '@babel/runtime/helpers/esm/objectWithoutProperties';
import { UPDATE_MODEL_EVENT, CHANGE_EVENT, CLOSE_EVENT } from '../_util/constants';
import getPrefixCls from '../_util/getPrefixCls';
import { useNormalModel } from '../_util/use/useModel';
import { flatten } from '../_util/vnode';
import { useTheme } from '../_theme/useTheme';
import PlusOutlined from '../icon/PlusOutlined';
import Scrollbar from '../scrollbar';
import { COMPONENT_NAME, ADD_EVENT, CLICK_TAB_EVENT, TABS_INJECTION_KEY } from './constants';
import { mapTabPane } from './helper';
import Tab from './tab';
import TabPane from './tab-pane.js';
import { tabsProps } from './props';

const _excluded = ["render", "renderTab"];
const prefixCls = getPrefixCls('tabs');
var tabs = defineComponent({
  name: COMPONENT_NAME,
  props: tabsProps,
  emits: [UPDATE_MODEL_EVENT, CHANGE_EVENT, CLOSE_EVENT, ADD_EVENT, CLICK_TAB_EVENT],
  setup(props, _ref) {
    let {
      emit,
      slots
    } = _ref;
    useTheme();
    const [currentValue, updateCurrentValue] = useNormalModel(props, emit);
    const tabPaneLazyCache = {};
    const tabRefs = ref([]);
    const tabNavRef = ref(null);
    const tabsLength = ref(0);
    const isCard = computed(() => props.type === 'card');
    const position = computed(() => isCard.value ? 'top' : props.position);
    const setTabRefs = (el, index) => {
      if (el) {
        tabRefs.value[index] = el;
      }
    };
    const handleTabClick = key => {
      if (key !== currentValue.value) {
        updateCurrentValue(key);
        emit(CHANGE_EVENT, key);
      }
      emit(CLICK_TAB_EVENT, key);
    };
    const handleAddClick = event => {
      emit(ADD_EVENT, event);
    };
    const handleClose = key => {
      emit(CLOSE_EVENT, key);
    };
    const autoScrollTab = el => {
      if (!tabNavRef.value || !el) {
        return;
      }
      const {
        scrollLeft,
        scrollTop,
        offsetWidth,
        offsetHeight
      } = tabNavRef.value.containerRef;
      if (['top', 'bottom'].includes(props.position) && (scrollLeft + offsetWidth < el.offsetLeft + el.offsetWidth || el.offsetLeft < scrollLeft)) {
        tabNavRef.value.setScrollLeft(el.offsetLeft - offsetWidth + el.offsetWidth, 0);
      } else if (['left', 'right'].includes(props.position) && (scrollTop + offsetHeight < el.offsetTop + el.offsetHeight || el.offsetTop < scrollTop)) {
        tabNavRef.value.setScrollTop(el.offsetTop - offsetHeight + el.offsetHeight, 0);
      }
    };

    // 当没有默认值时，设置第一项为默认值，在Tab组件调用
    const setDefaultValue = value => {
      if (!currentValue.value && currentValue.value !== 0) {
        updateCurrentValue(value);
      }
    };
    provide(TABS_INJECTION_KEY, {
      valueRef: currentValue,
      closableRef: toRef(props, 'closable'),
      closeModeRef: toRef(props, 'closeMode'),
      isCard,
      tabsLength,
      handleTabClick,
      handleClose,
      setDefaultValue
    });
    watch(() => [currentValue.value, position.value], () => {
      nextTick(() => {
        const tab = tabRefs.value.find(item => item.value === currentValue.value);
        autoScrollTab(tab === null || tab === void 0 ? void 0 : tab.$el);
      });
    }, {
      immediate: true
    });
    const mergeRenderPanes = () => {
      var _props$panes;
      const children = slots.default && flatten(slots.default()).filter(vNode => vNode.type.name === 'FTabPane') || [];
      if ((_props$panes = props.panes) !== null && _props$panes !== void 0 && _props$panes.length) {
        return children.concat(props.panes.map(pane => {
          const {
              render,
              renderTab
            } = pane,
            paneProps = _objectWithoutProperties(pane, _excluded);
          if (!render) {
            console.warn(`[${COMPONENT_NAME}]: panes 需要提供 render`);
          }
          const slots = {
            default: () => render === null || render === void 0 ? void 0 : render(paneProps),
            tab: renderTab ? () => renderTab(paneProps) : null
          };
          return createVNode(TabPane, mergeProps(paneProps, {
            "value": paneProps.value
          }), slots);
        }));
      }
      return children;
    };
    return () => {
      const children = mergeRenderPanes();
      let navItems = children.map((vNode, index) => {
        var _vNode$children;
        const tabSlot = (_vNode$children = vNode.children) === null || _vNode$children === void 0 ? void 0 : _vNode$children.tab;
        return createVNode(Tab, mergeProps(vNode.props, {
          "ref": el => setTabRefs(el, index)
        }), {
          default: tabSlot
        });
      });
      if (isCard.value) {
        if (props.addable) {
          navItems.push(createVNode("div", {
            "onClick": handleAddClick,
            "class": `${prefixCls}-tab ${prefixCls}-tab-card addable`
          }, [createVNode(PlusOutlined, null, null)]));
        }
        // 添加 card pad
        navItems = navItems.map((item, index) => [item, createVNode("div", {
          "class": index !== navItems.length - 1 ? `${prefixCls}-tab-pad` : `${prefixCls}-tab-pad--last`
        }, null)]).flat(1);
      }
      return createVNode("div", {
        "class": {
          [`${prefixCls}`]: true,
          [`${prefixCls}-${position.value}`]: true,
          [`${prefixCls}-card`]: isCard.value
        }
      }, [createVNode("div", {
        "class": `${prefixCls}-nav`
      }, [slots.prefix && createVNode("div", {
        "class": `${prefixCls}-nav-prefix`
      }, [slots.prefix()]), createVNode(Scrollbar, {
        "ref": tabNavRef,
        "class": `${prefixCls}-nav-scroll`,
        "shadow": true
      }, {
        default: () => [createVNode("div", {
          "class": `${prefixCls}-nav-scroll-content`
        }, [navItems])]
      }), slots.suffix && createVNode("div", {
        "class": `${prefixCls}-nav-suffix`
      }, [slots.suffix()])]), createVNode("div", {
        "class": `${prefixCls}-tab-pane-wrapper`
      }, [createVNode(TransitionGroup, {
        "name": props.transition ? props.transition === true ? `${prefixCls}-slide-fade` : props.transition : null
      }, {
        default: () => [mapTabPane(mergeRenderPanes(),
        // TODO: 待优化
        currentValue.value, tabPaneLazyCache)]
      })])]);
    };
  }
});

export { tabs as default };
