<script type="text/jsx">
import Emitter from 'heiner-ui/src/mixins/emitter';
import Migrating from 'heiner-ui/src/mixins/migrating';
import { addClass, removeClass, hasClass } from 'heiner-ui/src/utils/dom';

export default {
  name: 'HnSideMenu',

  componentName: 'HnSideMenu',

  render(h) {
    const component = (
      <ul
        role="sideMenuBar"
        key={+this.collapse}
        style={{ backgroundColor: this.backgroundColor }}
        class={{
          'hn-side-menu--collapse': this.collapse,
          "hn-side-menu": true
        }}
      >
        {this.$slots.default}
      </ul>
    );

    if (this.collapseTransition) {
      return (
        <hn-side-menu-collapse-transition>
          {component}
        </hn-side-menu-collapse-transition>
      );
    } else {
      return component;
    }
  },

  mixins: [Emitter, Migrating],

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

  components: {
    'hn-side-menu-collapse-transition': {
      functional: true,
      render(createElement, context) {
        const data = {
          props: {
            mode: 'out-in'
          },
          on: {
            beforeEnter(el) {
              el.style.opacity = 0.2;
            },

            enter(el) {
              addClass(el, 'hn-opacity-transition');
              el.style.opacity = 1;
            },

            afterEnter(el) {
              removeClass(el, 'hn-opacity-transition');
              el.style.opacity = '';
            },

            beforeLeave(el) {
              if (!el.dataset) el.dataset = {};

              if (hasClass(el, 'hn-side-menu--collapse')) {
                removeClass(el, 'hn-side-menu--collapse');
                el.dataset.oldOverflow = el.style.overflow;
                el.dataset.scrollWidth = el.clientWidth;
                addClass(el, 'hn-side-menu--collapse');
              } else {
                addClass(el, 'hn-side-menu--collapse');
                el.dataset.oldOverflow = el.style.overflow;
                el.dataset.scrollWidth = el.clientWidth;
                removeClass(el, 'hn-side-menu--collapse');
              }

              el.style.width = el.scrollWidth + 'px';
              el.style.overflow = 'hidden';
            },

            leave(el) {
              addClass(el, 'horizontal-collapse-transition');
              el.style.width = el.dataset.scrollWidth + 'px';
            }
          }
        };
        return createElement('transition', data, context.children);
      }
    }
  },

  props: {
    defaultActive: {
      type: String,
      default: ''
    },
    defaultOpeneds: Array,
    uniqueOpened: Boolean,
    router: Boolean,
    collapse: Boolean,
    collapseTransition: {
      type: Boolean,
      default: true
    },
    backgroundColor: {
      type: String,
      default: '#25262A'
    },
    textColor: {
      type: String,
      default: '#909399'
    },
    activeTextColor: {
      type: String,
      default: '#409EFF'
    },
    // new add - 文字颜色
    hoverTextColor: {
      type: String,
      default: '#fff'
    },
    openedTextColor: {
      type: String,
      default() {
        return this.hoverTextColor;
      }
    },
    activeMarkColor: {
      type: String,
      default() {
        return this.activeTextColor;
      }
    },
    // new add - 背景色
    openedBackground: {
      type: String,
      default: '#16181c'
    },
    activeBackground: {
      type: String,
      default: '#030304'
    },
    hoverBackground: {
      type: String,
      default() {
        return this.activeBackground;
      }
    },
  },
  data() {
    return {
      activeIndex: this.defaultActive,
      openedSideMenus: (this.defaultOpeneds && !this.collapse) ? this.defaultOpeneds.slice(0) : [],
      sideItems: {},
      sideSubmenus: {}
    };
  },
  computed: {
    isSideMenuPopup() {
      return this.collapse;
    }
  },
  watch: {
    defaultActive(value) {
      if (!this.sideItems[value]) {
        this.activeIndex = null
      }
      this.updateActiveIndex(value)
    },

    defaultOpeneds(value) {
      if (!this.collapse) {
        this.openedSideMenus = value;
      }
    },

    collapse(value) {
      if (value) this.openedSideMenus = [];
      this.broadcast('HnSideSubmenu', 'toggle-collapse', value);
    }
  },
  methods: {
    updateActiveIndex(val) {
      const item = this.sideItems[val] || this.sideItems[this.activeIndex] || this.sideItems[this.defaultActive];
      if (item) {
        this.activeIndex = item.index;
        this.initOpenedSideMenu();
      } else {
        this.activeIndex = null;
      }
    },
    addSideItem(item) {
      this.$set(this.sideItems, item.index, item);
    },
    removeSideItem(item) {
      delete this.sideItems[item.index];
    },
    addSideSubmenu(item) {
      this.$set(this.sideSubmenus, item.index, item);
    },
    removeSideSubmenu(item) {
      delete this.sideSubmenus[item.index];
    },
    openSideMenu(index, indexPath) {
      let openedSideMenus = this.openedSideMenus;
      if (openedSideMenus.indexOf(index) !== -1) return;
      // 将不在该菜单路径下的其余菜单收起
      // collapse all menu that are not under current menu item
      if (this.uniqueOpened) {
        this.openedSideMenus = openedSideMenus.filter(index => {
          return indexPath.indexOf(index) !== -1;
        });
      }
      this.openedSideMenus.push(index);
    },
    closeSideMenu(index) {
      const i = this.openedSideMenus.indexOf(index);
      if (i !== -1) {
        this.openedSideMenus.splice(i, 1);
      }
    },
    handleSideSubmenuClick(sideSubmenu) {
      const { index, indexPath } = sideSubmenu;
      let isOpened = this.openedSideMenus.indexOf(index) !== -1;

      if (isOpened) {
        this.closeSideMenu(index);
        this.$emit('close', index, indexPath);
      } else {
        this.openSideMenu(index, indexPath);
        this.$emit('open', index, indexPath);
      }
    },
    handleSideItemClick(item) {
      const { index, indexPath } = item;
      const oldActiveIndex = this.activeIndex;
      const hasIndex = item.index !== null;

      if (hasIndex) {
        this.activeIndex = item.index;
      }

      this.$emit('select', index, indexPath, item);

      if (this.collapse) {
        this.openedSideMenus = [];
      }

      if (this.router && hasIndex) {
        this.routeToItem(item, (error) => {
          this.activeIndex = oldActiveIndex;
          if (error) console.error(error);
        });
      }
    },
    // 初始化展开菜单
    // initialize opened menu
    initOpenedSideMenu() {
      const index = this.activeIndex;
      const activeItem = this.sideItems[index];
      if (!activeItem || this.collapse) return;

      let indexPath = activeItem.indexPath;

      // 展开该菜单项的路径上所有子菜单
      // expand all sideSubmenus of the menu item
      indexPath.forEach(index => {
        let sideSubmenu = this.sideSubmenus[index];
        sideSubmenu && this.openSideMenu(index, sideSubmenu.indexPath);
      });
    },
    routeToItem(item, onError) {
      let route = item.route || item.index;
      try {
        this.$router.push(route, () => { }, onError);
      } catch (e) {
        console.error(e);
      }
    },
    open(index) {
      const { indexPath } = this.sideSubmenus[index.toString()];
      indexPath.forEach(i => this.openSideMenu(i, indexPath));
    },
    close(index) {
      this.closeSideMenu(index);
    }
  },
  mounted() {
    this.initOpenedSideMenu();
    this.$on('side-item-click', this.handleSideItemClick);
    this.$on('side-submenu-click', this.handleSideSubmenuClick);
    this.$watch('sideItems', this.updateActiveIndex);
  }
};
</script>