<script>
import HnCollapseTransition from 'heiner-ui/src/transitions/collapse-transition';
import SideMenuMixin from './side-menu-mixin';
import Emitter from 'heiner-ui/src/mixins/emitter';
import Popper from 'heiner-ui/src/utils/vue-popper';
const PoperMixin = {
  props: {
    transformOrigin: {
      type: [Boolean, String],
      default: false
    },
    offset: Popper.props.offset,
    boundariesPadding: Popper.props.boundariesPadding,
    popperOptions: Popper.props.popperOptions
  },
  data: Popper.data,
  methods: Popper.methods,
  beforeDestroy: Popper.beforeDestroy,
  deactivated: Popper.deactivated
};
export default {
  name: 'HnSideSubmenu',
  componentName: 'HnSideSubmenu',
  mixins: [SideMenuMixin, Emitter, PoperMixin],
  components: { HnCollapseTransition },
  props: {
    index: {
      type: String,
      required: true
    },
    showTimeout: {
      type: Number,
      default: 300
    },
    hideTimeout: {
      type: Number,
      default: 300
    },
    popperClass: String,
    disabled: Boolean,
    popperAppendToBody: {
      type: Boolean,
      default: undefined
    }
  },
  data() {
    return {
      popperJS: null,
      timeout: null,
      items: {},
      sideSubmenus: {},
      mouseInChild: false
    };
  },
  watch: {
    opened(val) {
      if (this.isSideMenuPopup) {
        this.$nextTick(_ => {
          this.updatePopper();
        });
      }
    }
  },
  computed: {
    // popper option
    appendToBody() {
      return this.popperAppendToBody === undefined
        ? this.isFirstLevel
        : this.popperAppendToBody;
    },
    menuTransitionName() {
      return this.rootSideMenu.collapse ? 'hn-zoom-in-left' : 'hn-zoom-in-top';
    },
    opened() {
      return this.rootSideMenu.openedSideMenus.indexOf(this.index) > -1;
    },
    active() {
      let isActive = false;
      const sideSubmenus = this.sideSubmenus;
      const items = this.items;
      Object.keys(items).forEach(index => {
        if (items[index].active) {
          isActive = true;
        }
      });
      Object.keys(sideSubmenus).forEach(index => {
        if (sideSubmenus[index].active) {
          isActive = true;
        }
      });
      return isActive;
    },
    hoverBackground() {
      return this.rootSideMenu.hoverBackground;
    },
    backgroundColor() {
      // 一级菜单
      if (this.isFirstLevel) {
        return this.rootSideMenu.backgroundColor;
      }
      // 二级及以下菜单
      return this.rootSideMenu.openedBackground;
    },
    openedTextColor() {
      return this.rootSideMenu.openedTextColor;
    },
    textColor() {
      return this.rootSideMenu.textColor;
    },
    hoverTextColor() {
      return this.rootSideMenu.hoverTextColor;
    },
    isSideMenuPopup() {
      return this.rootSideMenu.isSideMenuPopup;
    },
    titleStyle() {
      return {
        color: (this.opened || this.active)
          ? this.openedTextColor
          : this.textColor
      };
    },
    isFirstLevel() {
      let isFirstLevel = true;
      let parent = this.$parent;
      while (parent && parent !== this.rootSideMenu) {
        if (['HnSideSubmenu'].indexOf(parent.$options.componentName) > -1) {
          isFirstLevel = false;
          break;
        } else {
          parent = parent.$parent;
        }
      }
      return isFirstLevel;
    }
  },
  methods: {
    handleCollapseToggle(value) {
      if (value) {
        this.initPopper();
      } else {
        this.doDestroy();
      }
    },
    addSideItem(item) {
      this.$set(this.items, item.index, item);
    },
    removeSideItem(item) {
      delete this.items[item.index];
    },
    addSideSubmenu(item) {
      this.$set(this.sideSubmenus, item.index, item);
    },
    removeSideSubmenu(item) {
      delete this.sideSubmenus[item.index];
    },
    handleClick() {
      const { rootSideMenu, disabled } = this;
      if (rootSideMenu.collapse || disabled) {
        return;
      }
      this.dispatch('HnSideMenu', 'side-submenu-click', this);
    },
    handleMouseenter(event, showTimeout = this.showTimeout) {
      if (!('ActiveXObject' in window) && event.type === 'focus' && !event.relatedTarget) {
        return;
      }
      const { rootSideMenu, disabled } = this;
      if (!rootSideMenu.collapse || disabled) {
        return;
      }
      this.dispatch('HnSideSubmenu', 'mouse-enter-child');
      clearTimeout(this.timeout);
      this.timeout = setTimeout(() => {
        this.rootSideMenu.openSideMenu(this.index, this.indexPath);
      }, showTimeout);
      if (this.appendToBody) {
        this.$parent.$el.dispatchEvent(new MouseEvent('mouseenter'));
      }
    },
    handleMouseleave(deepDispatch = false) {
      const { rootSideMenu } = this;
      if (!rootSideMenu.collapse) {
        return;
      }
      this.dispatch('HnSideSubmenu', 'mouse-leave-child');
      clearTimeout(this.timeout);
      this.timeout = setTimeout(() => {
        !this.mouseInChild && this.rootSideMenu.closeSideMenu(this.index);
      }, this.hideTimeout);
      if (this.appendToBody && deepDispatch) {
        if (this.$parent.$options.name === 'HnSideSubmenu') {
          this.$parent.handleMouseleave(true);
        }
      }
    },
    handleTitleMouseenter() {
      const title = this.$refs['side-submenu-title'];
      if (title) {
        title.style.backgroundColor = this.hoverBackground;
        title.style.color = this.hoverTextColor;
      }
    },
    handleTitleMouseleave() {
      const title = this.$refs['side-submenu-title'];
      if (title) {
        title.style.backgroundColor = this.backgroundColor;
        title.style.color = this.titleStyle.color;
      }
    },
    updatePlacement() {
      this.currentPlacement = 'right-start';
    },
    initPopper() {
      this.referenceElm = this.$el;
      this.popperElm = this.$refs.sideMenu;
      this.updatePlacement();
    }
  },
  created() {
    this.$on('toggle-collapse', this.handleCollapseToggle);
    this.$on('mouse-enter-child', () => {
      this.mouseInChild = true;
      clearTimeout(this.timeout);
    });
    this.$on('mouse-leave-child', () => {
      this.mouseInChild = false;
      clearTimeout(this.timeout);
    });
  },
  mounted() {
    this.parentSideMenu.addSideSubmenu(this);
    this.rootSideMenu.addSideSubmenu(this);
    this.initPopper();
  },
  beforeDestroy() {
    this.parentSideMenu.removeSideSubmenu(this);
    this.rootSideMenu.removeSideSubmenu(this);
  },
  render(h) {
    const {
      active,
      opened,
      paddingStyle,
      titleStyle,
      rootSideMenu,
      backgroundColor,
      currentPlacement,
      menuTransitionName,
      disabled,
      popperClass,
      $slots
    } = this;
    const popupSideMenu = (
      <transition name={menuTransitionName}>
        <div
          ref="sideMenu"
          v-show={opened}
          class={['hn-side-menu--vertical', popperClass]}
          on-mouseenter={($event) => this.handleMouseenter($event, 100)}
          on-mouseleave={() => this.handleMouseleave(true)}
          on-focus={($event) => this.handleMouseenter($event, 100)}>
          <ul
            role="sideMenu"
            class={['hn-side-menu hn-side-menu--popup', `hn-side-menu--popup-${currentPlacement}`]}
            style={{ backgroundColor: rootSideMenu.openedBackground }}>
            {$slots.default}
          </ul>
        </div>
      </transition>
    );
    const inlineSideMenu = (
      <hn-collapse-transition>
        <ul
          role="sideMenu"
          class="hn-side-menu hn-side-menu--inline"
          v-show={opened}
          style={{ backgroundColor: rootSideMenu.openedBackground }}>
          {$slots.default}
        </ul>
      </hn-collapse-transition>
    );
    const sideSubmenuTitleIcon = !rootSideMenu.collapse
      ? 'hn-icon-arrow-down' : 'hn-icon-arrow-right';
    return (
      <li
        class={{
          'hn-side-submenu': true,
          'is-active': active,
          'is-opened': opened,
          'is-disabled': disabled
        }}
        role="menuitem"
        aria-haspopup="true"
        aria-expanded={opened}
        on-mouseenter={this.handleMouseenter}
        on-mouseleave={() => this.handleMouseleave(false)}
        on-focus={this.handleMouseenter}
      >
        <div
          class="hn-side-submenu__title"
          ref="side-submenu-title"
          on-click={this.handleClick}
          on-mouseenter={this.handleTitleMouseenter}
          on-mouseleave={this.handleTitleMouseleave}
          style={[paddingStyle, titleStyle, { backgroundColor }]}
        >
          {$slots.title}
          <i class={['hn-side-submenu__icon-arrow', sideSubmenuTitleIcon]}></i>
        </div>
        {this.isSideMenuPopup ? popupSideMenu : inlineSideMenu}
      </li >
    );
  }
};
</script>