import { Namespace } from '@ibiz-template/core';
import {
  AppMenuModel,
  AppMenuItemModel,
  IPSAppMenuItem,
  IPSAppIndexView,
} from '@ibiz-template/model';
import {
  useAppMenuController,
  useNamespace,
  useRouter,
} from '@ibiz-template/vue-util';
import {
  defineComponent,
  getCurrentInstance,
  onMounted,
  onUnmounted,
  PropType,
  Ref,
  ref,
  watch,
} from 'vue';
import { AppMenuController } from '@ibiz-template/controller';
import '@ibiz-template/theme/style/components/widgets/app-menu/app-menu.scss';
import { AppCounter, CounterService } from '@ibiz-template/service';
/**
 * 递归生成菜单数据，递给 antd 的 Menu 组件
 *
 * @author chitanda
 * @date 2022-07-25 10:07:28
 * @param {AppMenuItemModel[]} items
 * @return {*}  {any[]}
 */
function getMenus(items: AppMenuItemModel[]): IData[] {
  return items.map(item => {
    const data: IData = {
      key: item.source.id,
      label: item.label,
      image: item.image,
      counterId: item.counterId,
    };
    if (item.children) {
      data.children = getMenus(item.children);
    }
    return data;
  });
}

/**
 * 绘制菜单项
 * @author lxm
 * @date 2022-08-16 14:08:20
 * @param {IData} menu
 * @returns {*}
 */
function renderMenuItem(
  menu: IData,
  collapseChange: boolean,
  ns: Namespace,
  c: AppMenuController,
  counterData: IData,
) {
  if (!c.menuItemsState[menu.key].visible) {
    return;
  }
  const target = c.model.items.find(item => {
    return item.id === menu.key;
  });
  if (target?.itemType === 'SEPERATOR') {
    return <div class={ns.e('menu-seperator')}></div>;
  }
  return !collapseChange ? (
    <i-menu-item class={ns.e('item')} name={menu.key}>
      <app-icon class={ns.e('icon')} icon={menu.image}></app-icon>
      {menu.label}
      {typeof counterData[menu.counterId] === 'number' ? (
        <i-badge
          class={ns.e('counter')}
          count={counterData[menu.counterId]}
        ></i-badge>
      ) : null}
    </i-menu-item>
  ) : (
    <i-tooltip
      class={ns.b('tooltip')}
      content={menu.label}
      placement={'right'}
      theme='light'
    >
      <i-menu-item class={ns.e('item')} name={menu.key}>
        <app-icon class={ns.e('icon')} icon={menu.image}></app-icon>
        {!menu.image ? menu.label.slice(0, 1) : null}
        {typeof counterData[menu.counterId] === 'number' ? (
          <i-badge
            class={ns.e('counter')}
            count={counterData[menu.counterId]}
          ></i-badge>
        ) : null}
      </i-menu-item>
    </i-tooltip>
  );
}

/**
 * 绘制中间菜单项
 * @author fzh
 * @date 2022-08-29 14:08:20
 * @param {IData} menu
 * @returns {*}
 */
function renderCenterChildren(
  menu: IData,
  ns: Namespace,
  c: AppMenuController,
  counterData: IData,
  click: Function,
) {
  if (!c.menuItemsState[menu.key].visible) {
    return;
  }
  return (
    <div class={ns.e('cchildren')} onClick={() => click(menu.key)}>
      <app-icon class={ns.e('cchildrenIcon')} icon={menu.image}></app-icon>
      <div class={ns.em('cchildren', 'title')}>
        <span>{menu.label}</span>
      </div>
      {typeof counterData[menu.counterId] === 'number' ? (
        <i-badge
          class={ns.e('counter')}
          count={counterData[menu.counterId]}
        ></i-badge>
      ) : null}
    </div>
  );
}

/**
 * 绘制中间菜单分组
 * @author fzh
 * @date 2022-08-29 14:08:20
 * @param {IData} menu
 * @returns {*}
 */
function renderCenterMenuItem(
  menu: IData,
  ns: Namespace,
  c: AppMenuController,
  counterData: IData,
  click: Function,
) {
  if (!c.menuItemsState[menu.key].visible) {
    return;
  }
  return (
    <div class={ns.e('cmenu')}>
      <div class={ns.em('cmenu', 'title')}>{menu.label}</div>
      {typeof counterData[menu.counterId] === 'number' ? (
        <i-badge
          class={ns.e('counter')}
          count={counterData[menu.counterId]}
        ></i-badge>
      ) : null}
      <div class={ns.e('cmenucontent')}>
        {menu.children?.length > 0 &&
          menu.children.map((item: IData) => {
            return renderCenterChildren(item, ns, c, counterData, click);
          })}
      </div>
    </div>
  );
}

/**
 * 绘制收缩分组菜单项
 * @param {IData} menu
 * @return {*}
 * @author: zhujiamin
 * @Date: 2022-09-08 16:39:15
 */
function renderDropDownMenuItem(
  menu: IData,
  collapseChange: boolean,
  ns: Namespace,
  c: AppMenuController,
  counterData: IData,
) {
  if (!c.menuItemsState[menu.key].visible) {
    return;
  }
  return (
    <i-dropdown-item class={ns.be('submenu', 'item')} name={menu.key}>
      <i-menu-item name={menu.key}>
        <app-icon class={ns.e('icon')} icon={menu.image}></app-icon>
        {menu.label}
        {typeof counterData[menu.counterId] === 'number' ? (
          <i-badge
            class={ns.e('counter')}
            count={counterData[menu.counterId]}
          ></i-badge>
        ) : null}
      </i-menu-item>
    </i-dropdown-item>
  );
}

/**
 * 绘制子菜单
 * @author lxm
 * @date 2022-08-16 14:08:29
 * @param {IData} subMenu
 * @returns {*}
 */
function renderSubmenu(
  isFirst: boolean,
  subMenu: IData,
  collapseChange: boolean,
  ns: Namespace,
  c: AppMenuController,
  counterData: IData,
) {
  if (!c.menuItemsState[subMenu.key].visible) {
    return;
  }
  return !collapseChange ? (
    <i-submenu name={subMenu.key}>
      <template slot='title'>
        <app-icon class={ns.e('icon')} icon={subMenu.image}></app-icon>
        {subMenu.label}
      </template>
      {subMenu.children.map((item: IData) => {
        if (item.children) {
          return renderSubmenu(false, item, collapseChange, ns, c, counterData);
        }
        return renderMenuItem(item, collapseChange, ns, c, counterData);
      })}
    </i-submenu>
  ) : (
    <i-dropdown
      placement='right'
      class={ns.b('submenu')}
      transfer
      transfer-class-name={ns.b('submenu-transfer')}
    >
      <div class={ns.be('submenu', 'title')}>
        {isFirst
          ? [
              <app-icon class={ns.e('icon')} icon={subMenu.image}></app-icon>,
              !subMenu.image ? subMenu.label.slice(0, 1) : null,
            ]
          : [
              <app-icon class={ns.e('icon')} icon={subMenu.image}></app-icon>,
              subMenu.label,
            ]}
        {isFirst ? null : <i-icon type='ios-arrow-forward' />}
      </div>
      <i-dropdown-menu class={ns.be('submenu', 'list')} slot='list'>
        {subMenu.children.map((item: IData) => {
          if (item.children) {
            return renderSubmenu(
              false,
              item,
              collapseChange,
              ns,
              c,
              counterData,
            );
          }
          return renderDropDownMenuItem(
            item,
            collapseChange,
            ns,
            c,
            counterData,
          );
        })}
      </i-dropdown-menu>
    </i-dropdown>
  );
}

export const AppMenu = defineComponent({
  name: 'AppMenu',
  props: {
    modelData: AppMenuModel,
    context: { type: Object as PropType<IContext>, required: true },
    collapseChange: Boolean,
    currentPath: String,
    menuModel: { type: Object as PropType<IPSAppIndexView>, required: false },
  },
  setup(props, { emit }) {
    const { proxy } = getCurrentInstance()!;
    const c = useAppMenuController(proxy, props.modelData!, props.context!, {});
    const menus = ref<IData[]>([]);
    // 默认激活菜单项
    const defaultActive = ref('');
    // 默认展开菜单项数组
    const defaultOpens: Ref<string[]> = ref([]);
    // 路由对象
    const route = proxy.$route;
    // 计数器数据
    let counter: AppCounter | null = null;
    const counterData = ref<IData>({});

    const menuDirection = props.menuModel?.mainMenuAlign;

    c.nerve.self.evt.on('created', () => {
      menus.value = getMenus(c.model.items);
    });

    let cacheFullPath = '';

    const onClick = async (key: string) => {
      cacheFullPath = proxy.$route.fullPath;
      await c.onClickMenuItem(key);
      cacheFullPath = '';
    };

    const ns = useNamespace('app-menu');

    // 手动更新iView菜单
    const updateMenu = () => {
      setTimeout(() => {
        if (proxy.$refs.menu) {
          const menu: IData = proxy.$refs.menu;
          menu.updateActiveName();
          menu.updateOpened();
        }
      }, 500);
    };

    const router = useRouter(proxy);
    router.beforeEach((to, from, next) => {
      if (from.fullPath === cacheFullPath) {
        emit('menuRouteChange');
      }
      next();
    });

    // 菜单选中回显，监听视图传进来的currentPath
    watch(
      () => props.currentPath,
      (newVal, oldVal) => {
        // 新旧值不一样，且新值不为空时变更
        if (newVal !== oldVal && newVal) {
          const findItem = c.model.allItems.find(item => {
            return item.viewModelPath === newVal;
          });
          if (findItem) {
            defaultActive.value = findItem.source.id;
            updateMenu();
          }
        }
      },
      { deep: true, immediate: true },
    );

    // 处理默认展开父菜单
    const handleDefaultOpen = (parent: IPSAppMenuItem) => {
      if (parent && parent.itemType === 'MENUITEM') {
        const findIndex = defaultOpens.value.findIndex(open => {
          return open === parent.id;
        });
        if (findIndex === -1) {
          defaultOpens.value.push(parent.id);
        }
        const gParent = parent.getParentPSModelObject() as IPSAppMenuItem;
        if (gParent) {
          handleDefaultOpen(gParent);
        }
      }
    };

    // 回显完成后，遍历展开父菜单
    watch(
      () => defaultActive.value,
      newVal => {
        const findItem = c.model.allItems.find(item => {
          return newVal === item.id;
        });
        if (findItem) {
          const parent =
            findItem.source.getParentPSModelObject() as IPSAppMenuItem;
          // 遍历取父菜单项
          handleDefaultOpen(parent);
          updateMenu();
        }
      },
    );

    onMounted(async () => {
      // 默认激活的菜单项
      const defaultActiveMenuItem = c.model.allItems.find(item => {
        return (
          item.source.openDefault &&
          !item.source.hidden &&
          c.menuItemsState[item.source.id].permitted
        );
      });

      if (defaultActiveMenuItem && !route.params.view2) {
        defaultActive.value = defaultActiveMenuItem.id;
        onClick(defaultActive.value);
      }
      // 默认展开的菜单项数组
      const defaultOpensArr = c.model.allItems.filter(item => {
        return item.source.expanded && !item.source.hidden;
      });
      if (defaultOpensArr.length > 0) {
        defaultOpensArr.forEach(item => {
          defaultOpens.value.push(item.id);
        });
      }
      updateMenu();

      // 计数器相关
      const CounterRef = c.model.source.getPSAppCounterRef();
      if (CounterRef) {
        counter = await CounterService.getCounterByRef(
          CounterRef,
          props.context,
        );
        counter.onChange(data => {
          counterData.value = data;
        });
      }
    });

    onUnmounted(() => {
      counter?.destroy();
    });

    return {
      menus,
      c,
      onClick,
      ns,
      defaultActive,
      defaultOpens,
      counterData,
      menuDirection,
    };
  },
  render() {
    if (this.menuDirection === 'CENTER') {
      return (
        <div class={[this.ns.b(), this.menuDirection?.toLowerCase()]}>
          {this.menus.map(item => {
            return renderCenterMenuItem(
              item,
              this.ns,
              this.c,
              this.counterData,
              this.onClick,
            );
          })}
        </div>
      );
    }
    return (
      <i-menu
        ref={'menu'}
        active-name={this.defaultActive}
        open-names={this.defaultOpens}
        on-on-select={this.onClick}
        theme='light'
        width='auto'
        class={[this.ns.b(), this.ns.is('collapse', this.collapseChange)]}
      >
        {this.menus.map(item => {
          if (item.children?.length > 0) {
            return renderSubmenu(
              true,
              item,
              this.collapseChange,
              this.ns,
              this.c,
              this.counterData,
            );
          }
          return renderMenuItem(
            item,
            this.collapseChange,
            this.ns,
            this.c,
            this.counterData,
          );
        })}
      </i-menu>
    );
  },
});
