<!--
 * @Description: 侧边栏
 * @Author: ZCY
 * @Date: 2022年12月1日16:13:51
-->
<script lang="ts" setup>
import type { ComputedRef, Ref } from 'vue';
import { computed, inject } from 'vue';
import { Icon } from '@iconify/vue';
import { cloneDeep } from 'lodash-es';
import { colorDarken, colorLighten, isDarkColor } from '@unyu/utils';
import { collapsedKey, configKey, menusKey, phoneFlagKey, routeKey, themeColorKey } from '../../utils/injectedKeys';
import TheMenu from '../menu/index.vue';
import type { AntMenu, LayoutConfig, ThemeColor } from './types';
import TheLogo from './TheLogo.vue';

const { route } = inject<{ route: ComputedRef<Record<string, any>> }>(routeKey)!;
const { config } = inject<{ config: Ref<LayoutConfig> }>(configKey)!;
const menus = inject<Ref<AntMenu[]>>(menusKey)!;
const { themeColor } = inject<{ themeColor: Ref<ThemeColor> }>(themeColorKey)!;
const { phoneFlag } = inject<{ phoneFlag: Ref<boolean> }>(phoneFlagKey)!;
const { collapsed, setCollapsed } = inject<{ collapsed: Ref<boolean>; setCollapsed: (flag: boolean) => void }>(
  collapsedKey
)!;

const sideBarStl = computed(() => {
  const navStyle = config.value.navStyle;
  const layout = config.value.layout;
  const nav = themeColor.value.nav;
  if (layout === 'default' && navStyle === 'dark') {
    return { backgroundColor: nav, color: '#eeeeee' };
  }
  return { backgroundColor: '#fff', color: '#191919' };
});

const collapsedIconBg = computed(() => {
  const menuBg =
    (config.value.layout === 'default' && config.value.navStyle === 'dark'
      ? themeColor.value.nav
      : themeColor.value.menuBg) || '#fff';
  if (isDarkColor(menuBg)) {
    return colorLighten(menuBg, 0.3).slice(0, 7);
  }
  return colorDarken(menuBg, 0.1).slice(0, 7);
});

const filterHiddenMenu = (list: AntMenu[]) => {
  const clonedMenus = cloneDeep(list);
  return clonedMenus
    .map(menu => {
      if (menu.meta?.isHidden) return undefined;
      if (menu.children?.length) menu.children = filterHiddenMenu(menu.children);
      return menu;
    })
    .filter(i => i) as AntMenu[];
};
const cloneMenuList = computed<AntMenu[]>(() => cloneDeep(menus.value));

const menuList = computed<AntMenu[]>(() => {
  if (config.value.layout === 'classic') {
    const pathKey = (route.value.path as string).split('/').filter(i => i)[0];
    const menu =
      cloneMenuList.value.find(i => i.key === `/${pathKey || ''}`) ||
      cloneMenuList.value.find(i => i.key === `${pathKey || ''}`);
    if (menu) {
      if (menu.children) {
        return filterHiddenMenu(menu.children);
      } else {
        return filterHiddenMenu([menu]);
      }
    }
    return [];
  }
  return filterHiddenMenu(cloneMenuList.value);
});

const handleMaskClick = () => {
  setCollapsed(true);
};
</script>

<template>
  <div
    v-if="config.isSidebar"
    id="sideBar"
    class="app-sidebar"
    :class="{
      'app-sidebar-drawer': phoneFlag,
      'app-sidebar-drawer-collapsed': phoneFlag && collapsed
    }"
    :style="sideBarStl"
  >
    <TheLogo v-if="config.layout === 'default'">
      <template #logo>
        <slot name="logo" />
      </template>
    </TheLogo>
    <div class="app-sidebar-menu">
      <TheMenu v-model:collapsed="collapsed" :items="menuList" style="position: relative !important" />
    </div>
    <div
      v-if="config.layout !== 'topBar'"
      class="app-sidebar-collapsed"
      :style="{ borderColor: collapsedIconBg }"
      @click="setCollapsed(!collapsed)"
    >
      <div>
        <Icon
          icon="ant-design:menu-fold-outlined"
          :style="{
            fontSize: '18px',
            transform: collapsed ? 'rotateY(180deg)' : 'rotateY(0deg)'
          }"
        />
      </div>
    </div>
    <teleport to="body">
      <div v-if="phoneFlag && !collapsed" class="app-sidebar-mask" @click="handleMaskClick" />
    </teleport>
  </div>
</template>

<style scoped>
.app-sidebar {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  height: 100%;
  width: auto;
  left: 0;
  bottom: 0;
  background-color: v-bind("themeColor.menuBg");
  color: v-bind("themeColor.menuColor");
  flex-shrink: 0;
  overflow: hidden;
  padding-bottom: 40px;
  border-inline-end: #eee 1px solid;
}

.app-sidebar-menu {
  position: relative;
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
}
.app-sidebar-menu::-webkit-scrollbar {
  width: 0;
  height: 0;
}
.app-sidebar-menu:hover::-webkit-scrollbar-track-piece {
  background: transparent;
}
.app-sidebar-menu:hover::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}
.app-sidebar-menu:hover::-webkit-scrollbar-thumb {
  background: #aaa;
  border-radius: 20px;
}

.app-sidebar-drawer {
  position: fixed;
  z-index: 1000;
  left: 0;
  height: 100%;
  width: 210px;
  transition: transform 0.3s ease 0s;
}
.app-sidebar-drawer-collapsed {
  transform: translateX(-100%);
}

.app-sidebar-mask {
  position: fixed;
  z-index: 999;
  inset: 0;
  background: rgba(0, 0, 0, 0.45);
  pointer-events: auto;
}

.app-sidebar-close {
  display: none !important;
  font-size: 1.5rem;
  color: v-bind("themeColor.menuColor");
  cursor: pointer;
  margin: 0.25rem;
}

.app-sidebar-close:hover {
  opacity: 95%;
}

@media (max-width: 768px) {
  .app-sidebar-close {
    display: flex !important;
  }
}
.app-sidebar-collapsed {
  position: absolute;
  bottom: 0;
  z-index: 100;
  display: flex;
  justify-content: flex-start;
  align-items: center;
  max-height: 40px;
  height: 40px;
  width: 100%;
  background-color: transparent;
  color: inherit;
  cursor: pointer;
  border-bottom-width: 0;
  border-left-width: 0;
  border-right-width: 0;
  border-top-width: 1px;
  border-style: solid;
  padding: 0.5rem 13px 0.5rem 13px;
}
.app-sidebar-collapsed div {
  border-radius: 3px;
}
.app-sidebar-collapsed:hover .iconify {
  opacity: 80%;
}

.iconify {
  display: flex;
  cursor: pointer;
  margin: 0.25rem;
}

.iconify:hover {
  opacity: 90%;
}
</style>
