import _extends from 'babel-runtime/helpers/extends';
import _defineProperty from 'babel-runtime/helpers/defineProperty';
import omit from 'omit.js';
import BaseMixin from '../../_util/BaseMixin';
import PropTypes from '../../_util/vue-types';
import raf from 'raf';
import KeyCode from './KeyCode';
import { getOptionProps } from '../../_util/props-util';
import { cloneElement } from '../../_util/vnode';
import Sentinel from './Sentinel';

function getDefaultActiveKey(props) {
  var activeKey = void 0;
  var children = props.children;
  children.forEach(function (child) {
    if (child && !activeKey && !child.disabled) {
      activeKey = child.key;
    }
  });
  return activeKey;
}

function activeKeyIsValid(props, key) {
  var children = props.children;
  var keys = children.map(function (child) {
    return child && child.key;
  });
  return keys.indexOf(key) >= 0;
}

export default {
  name: 'Tabs',
  mixins: [BaseMixin],
  model: {
    prop: 'activeKey',
    event: 'change'
  },
  props: {
    destroyInactiveTabPane: PropTypes.bool,
    renderTabBar: PropTypes.func.isRequired,
    renderTabContent: PropTypes.func.isRequired,
    navWrapper: PropTypes.func.def(function (arg) {
      return arg;
    }),
    children: PropTypes.any.def([]),
    prefixCls: PropTypes.string.def('ant-tabs'),
    tabBarPosition: PropTypes.string.def('top'),
    activeKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
    defaultActiveKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
    __propsSymbol__: PropTypes.any
  },
  data: function data() {
    var props = getOptionProps(this);
    var activeKey = void 0;
    if ('activeKey' in props) {
      activeKey = props.activeKey;
    } else if ('defaultActiveKey' in props) {
      activeKey = props.defaultActiveKey;
    } else {
      activeKey = getDefaultActiveKey(props);
    }
    return {
      _activeKey: activeKey
    };
  },
  provide: function provide() {
    return {
      sentinelContext: this
    };
  },

  watch: {
    __propsSymbol__: function __propsSymbol__() {
      var nextProps = getOptionProps(this);
      if ('activeKey' in nextProps) {
        this.setState({
          _activeKey: nextProps.activeKey
        });
      } else if (!activeKeyIsValid(nextProps, this.$data._activeKey)) {
        // https://github.com/ant-design/ant-design/issues/7093
        this.setState({
          _activeKey: getDefaultActiveKey(nextProps)
        });
      }
    }
  },
  beforeDestroy: function beforeDestroy() {
    this.destroy = true;
    raf.cancel(this.sentinelId);
  },

  methods: {
    onTabClick: function onTabClick(activeKey, e) {
      if (this.tabBar.componentOptions && this.tabBar.componentOptions.listeners && this.tabBar.componentOptions.listeners.tabClick) {
        this.tabBar.componentOptions.listeners.tabClick(activeKey, e);
      }
      this.setActiveKey(activeKey);
    },
    onNavKeyDown: function onNavKeyDown(e) {
      var eventKeyCode = e.keyCode;
      if (eventKeyCode === KeyCode.RIGHT || eventKeyCode === KeyCode.DOWN) {
        e.preventDefault();
        var nextKey = this.getNextActiveKey(true);
        this.onTabClick(nextKey);
      } else if (eventKeyCode === KeyCode.LEFT || eventKeyCode === KeyCode.UP) {
        e.preventDefault();
        var previousKey = this.getNextActiveKey(false);
        this.onTabClick(previousKey);
      }
    },
    onScroll: function onScroll(_ref) {
      var target = _ref.target,
          currentTarget = _ref.currentTarget;

      if (target === currentTarget && target.scrollLeft > 0) {
        target.scrollLeft = 0;
      }
    },


    // Sentinel for tab index
    setSentinelStart: function setSentinelStart(node) {
      this.sentinelStart = node;
    },
    setSentinelEnd: function setSentinelEnd(node) {
      this.sentinelEnd = node;
    },
    setPanelSentinelStart: function setPanelSentinelStart(node) {
      if (node !== this.panelSentinelStart) {
        this.updateSentinelContext();
      }
      this.panelSentinelStart = node;
    },
    setPanelSentinelEnd: function setPanelSentinelEnd(node) {
      if (node !== this.panelSentinelEnd) {
        this.updateSentinelContext();
      }
      this.panelSentinelEnd = node;
    },
    setActiveKey: function setActiveKey(activeKey) {
      if (this.$data._activeKey !== activeKey) {
        var props = getOptionProps(this);
        if (!('activeKey' in props)) {
          this.setState({
            _activeKey: activeKey
          });
        }
        this.__emit('change', activeKey);
      }
    },
    getNextActiveKey: function getNextActiveKey(next) {
      var activeKey = this.$data._activeKey;
      var children = [];
      this.$props.children.forEach(function (c) {
        if (c && !c.disabled && c.disabled !== '') {
          if (next) {
            children.push(c);
          } else {
            children.unshift(c);
          }
        }
      });
      var length = children.length;
      var ret = length && children[0].key;
      children.forEach(function (child, i) {
        if (child.key === activeKey) {
          if (i === length - 1) {
            ret = children[0].key;
          } else {
            ret = children[i + 1].key;
          }
        }
      });
      return ret;
    },
    updateSentinelContext: function updateSentinelContext() {
      var _this = this;

      if (this.destroy) return;

      raf.cancel(this.sentinelId);
      this.sentinelId = raf(function () {
        _this.$forceUpdate();
      });
    }
  },
  render: function render() {
    var _cls;

    var h = arguments[0];

    var props = this.$props;
    var prefixCls = props.prefixCls,
        navWrapper = props.navWrapper,
        tabBarPosition = props.tabBarPosition,
        renderTabContent = props.renderTabContent,
        renderTabBar = props.renderTabBar,
        destroyInactiveTabPane = props.destroyInactiveTabPane;

    var cls = (_cls = {}, _defineProperty(_cls, prefixCls, 1), _defineProperty(_cls, prefixCls + '-' + tabBarPosition, 1), _cls);

    this.tabBar = renderTabBar();
    var tabBar = cloneElement(this.tabBar, {
      props: {
        prefixCls: prefixCls,
        navWrapper: navWrapper,
        tabBarPosition: tabBarPosition,
        panels: props.children,
        activeKey: this.$data._activeKey
      },
      on: {
        keydown: this.onNavKeyDown,
        tabClick: this.onTabClick
      },
      key: 'tabBar'
    });
    var tabContent = cloneElement(renderTabContent(), {
      props: {
        prefixCls: prefixCls,
        tabBarPosition: tabBarPosition,
        activeKey: this.$data._activeKey,
        destroyInactiveTabPane: destroyInactiveTabPane
      },
      on: {
        change: this.setActiveKey
      },
      children: props.children,
      key: 'tabContent'
    });

    var sentinelStart = h(Sentinel, {
      key: 'sentinelStart',
      attrs: { setRef: this.setSentinelStart,
        nextElement: this.panelSentinelStart
      }
    });
    var sentinelEnd = h(Sentinel, {
      key: 'sentinelEnd',
      attrs: { setRef: this.setSentinelEnd,
        prevElement: this.panelSentinelEnd
      }
    });

    var contents = [];

    if (tabBarPosition === 'bottom') {
      contents.push(sentinelStart, tabContent, sentinelEnd, tabBar);
    } else {
      contents.push(tabBar, sentinelStart, tabContent, sentinelEnd);
    }
    var listeners = _extends({}, omit(this.$listeners, ['change']), {
      scroll: this.onScroll
    });
    return h(
      'div',
      { on: listeners, 'class': cls },
      [contents]
    );
  }
};