<template>
  <div class="hs-menu"
       :class="{ locked: isMenuSizeLocked,
                 expand: isMenuExpanded,
                 shrink: !isMenuExpanded}"
       @mouseenter="handleMenuSizeChanged('large')"
       @mouseleave="handleMenuSizeChanged('tiny')">
    <div class="hs-menu-wrapper">
      <menu-list :shrink = "!isMenuExpanded"
                 :origin-source = "menuSource"
                 :source = "menuSource"
                 :active-menu = "activeMenu"
                 :select = "select"
                 :is-active-parent-menu = "isActiveParentMenu"
                 :before-select = "beforeSelect">
      </menu-list>
    </div>
    <div class="hs-menu-trigger">
      <div class="trigger" @click="handleTriggerClick">
        <span v-show="isMenuSizeLocked">
          <img src="./images/lock.png" alt=""/>
          <span>解锁</span>
        </span>
        <span v-show="!isMenuSizeLocked">
          <img src="./images/unlock.png" alt=""/>
          <span>锁定</span>
        </span>
      </div>
    </div>
  </div>
</template>

<script>
  import MenuList from './menu-list';
  import menuService from './menu-service';

  export default {
    name: 'HsMenu',
    components: {
      MenuList,
    },
    props: {
      isActiveParentMenu: {
        type: Boolean,
        default: false,
      },
      source: {
        type: Array,
        default() {
          return [];
        },
      },
      activeMenu: [String, Object],
      select: {
        type: Function,
        default() {
          return {};
        },
      },
      beforeSelect: {
        type: Function,
        default() {
          return new Promise(resolve => {
            resolve();
          });
        },
      },
    },
    data() {
      return {
        isMenuSizeLocked: true,
        isMenuExpanded: true,
        menuSource: [],
        activeMenuCode: '',
      };
    },
    watch: {
      activeMenu(newMenu, oldMenu) {
        let activeCode = '';
        let oldCode = '';
        let triggerSelectEvent = true;
        const hasOwn = Object.prototype.hasOwnProperty;

        if (typeof newMenu === 'object') {
          activeCode = newMenu.menuCode;
          if (hasOwn.call(newMenu, 'triggerSelectEvent') && !newMenu.triggerSelectEvent) {
            triggerSelectEvent = false;
          }
        } else {
          activeCode = newMenu;
        }
        if (typeof oldMenu === 'object') {
          oldCode = oldMenu.menuCode;
        } else {
          const activeMenu = menuService.getCurrentSelected(this.menuSource);
          if (activeMenu) {
            oldCode = activeMenu.menuCode;
          }
        }

        this.activeMenuCode = activeCode;
        if (activeCode && activeCode !== oldCode) {
          if (!triggerSelectEvent) {
            menuService.activeMenuByCode(this.activeMenuCode, this.menuSource, this.isActiveParentMenu);
          } else {
            this.selectMenu();
          }
        } else if (typeof newMenu === 'object' && typeof oldMenu === 'object') {
          let newParams = newMenu.params;
          let oldParams = oldMenu.params;

          if (typeof newParams === 'object') {
            newParams = JSON.stringify(newParams);
          }
          if (typeof oldParams === 'object') {
            oldParams = JSON.stringify(oldParams);
          }
          if (newParams !== oldParams && triggerSelectEvent) {
            this.selectMenu();
          }
        }
      },
      source(newVal = [], oldVal = []) {
        const triggerSelectEvent = newVal.length > 0 && oldVal.length === 0;

        this.setSourceAndMenu(newVal, triggerSelectEvent);
      },
    },
    computed: {
    },
    mounted() {
      this.init();
    },
    methods: {
      init() {
        this.setSourceAndMenu(this.source);
      },
      /**
       * 移入、移出
       * @param size
       */
      handleMenuSizeChanged(size) {
        if (this.isMenuSizeLocked) return;
        if (size === 'large') {
          this.isMenuExpanded = true;
        } else if (size === 'tiny') {
          this.isMenuExpanded = false;
        }
      },

      /**
       * 锁定、解锁
       */
      handleTriggerClick() {
        this.isMenuSizeLocked = !this.isMenuSizeLocked;
        this.isMenuExpanded = true;
      },
      /**
       * 显示指定菜单通过code
       * @param menuCode
       */
      showMenuByCode(menuCode) {
        if ((typeof menuCode !== 'string' && !Array.isArray(menuCode)) || !menuCode) { // 传入非法值
          return;
        }
        if (!Array.isArray(menuCode)) { // 兼容字符串
          menuCode = [menuCode];
        }
        this.source.forEach(menu => {
          menuCode.some(code => {
            if (code === menu.menuCode) {
              menu.isShowMenu = true;
              return true;
            }
          });
          return false;
        });
        this.setSourceAndMenu(this.source, false);
      },
      hideMenuByCode(menuCode) {
        if ((typeof menuCode !== 'string' && !Array.isArray(menuCode)) || !menuCode) { // 传入非法值
          return;
        }
        if (!Array.isArray(menuCode)) { // 兼容字符串
          menuCode = [menuCode];
        }
        this.source.forEach(menu => {
          menuCode.some(code => {
            if (code === menu.menuCode) {
              menu.isShowMenu = false;
              return true;
            }
          });
          return false;
        });
        this.setSourceAndMenu(this.source, false);
      },
      setSourceAndMenu(source, triggerSelectEvent) {
        this.menuSource = menuService.getMenuSource(source);
        if (this.menuSource.length > 0) {
          this.setActiveMenuCode();
          this.setActiveMenu(triggerSelectEvent);
        }
      },
      setActiveMenuCode() {
        const activeMenuCode = typeof this.activeMenu === 'object' ? this.activeMenu.menuCode : this.activeMenu;
        this.activeMenuCode = activeMenuCode || menuService.getDefaultActiveMenuCode(this.menuSource);
      },
      /**
       * 设置激活的菜单
       */
      setActiveMenu(triggerSelectEvent = true) {
        const hasOwn = Object.prototype.hasOwnProperty;

        if (!this.activeMenuCode) {
          let activeMenu = menuService.getCurrentSelected(this.menuSource);

          if (activeMenu) { // 当前有激活的菜单
            menuService.unfoldParent(activeMenu);
          } else { // 当前没有激活的菜单，激活第一个菜单
            activeMenu = menuService.getFirstMenu(this.menuSource);
            if (activeMenu) {
              this.activeMenuCode = activeMenu.menuCode;
              if (typeof this.activeMenu === 'object' && (!hasOwn.call(this.activeMenu, 'triggerSelectEvent')
                || this.activeMenu.triggerSelectEvent)) {
                this.selectMenu();
              }
            }
          }
        } else if (!triggerSelectEvent || (typeof this.activeMenu === 'object' && (hasOwn.call(this.activeMenu, 'triggerSelectEvent')
            && !this.activeMenu.triggerSelectEvent))) {
          menuService.activeMenuByCode(this.activeMenuCode, this.menuSource, this.isActiveParentMenu);
        } else {
          this.selectMenu();
        }
      },
      /**
       * 激活菜单
       */
      selectMenu() {
        const menu = menuService.getMenuByCode(this.menuSource, this.activeMenuCode);
        if (menu) {
          this.beforeSelect(menu).then(() => {
            menuService.activeMenuByCode(menu.menuCode, this.menuSource, this.isActiveParentMenu);

            let params = '';
            if (this.activeMenu && typeof this.activeMenu === 'object') {
              params = this.activeMenu.params;
            }
            this.select({
              menu,
              params,
            });
          }).catch(() => {});
        }
      },
    },
  };
</script>

<style lang = "scss">
  .hs-menu {
    display: flex;
    flex-direction: column;
    height: 100%;
    font: 14px "Microsoft YaHei", Arial;
    transition: width .5s ease;
    &.expand {
       width: 180px;
      .hs-menu-trigger {
        .trigger {
          width: 76px;
        }
      }
    }
    &.shrink {
       width: 48px;
      .hs-menu-trigger {
        .trigger {
          width: 24px;
          overflow: hidden;
        }
      }
    }
    > .hs-menu-wrapper {
      flex: 1;
      overflow-x: hidden;
      background-color: #363f4e;
    }

    > .hs-menu-wrapper::-webkit-scrollbar {
      width: 8px;
      height: 8px;
   }
    > .hs-menu-wrapper::-webkit-scrollbar-thumb {
      border-radius: 8px;
      background-color: #9297a1;
      width: 0;
    }
    > .hs-menu-wrapper::-webkit-scrollbar-thumb:hover {
      background-color:#d1d3d8;
    }
    > .hs-menu-trigger {
      display: flex;
      justify-content: center;
      align-items: center;
      width: 100%;
      height: 48px;
      background-color: #363f4e;
      overflow: hidden;

      .trigger {
        height: 24px;
        line-height: 24px;
        text-align: center;
        border-radius: 12px;
        cursor: pointer;
        color: #b3b5ba;
        background-color: #273240;
        img {
          margin: 0 2px;
        }

        &:hover {
           color: #fff;
           background-color: #515c6e;
         }
      }
    }
  }
</style>
