<template>
  <div class="dc-breadcrumb-nav-view" :class="{ 'dc-breadcrumb-hidden-close': panes == null || panes.length <= 1 }">
    <a-tabs type="editable-card" v-model="activeKey" hide-add @tabClick="onTabClick" @edit="remove($event, true)">
      <a-tab-pane v-for="pane in panes" :key="pane.key">
        <template slot="tab">
          <span v-context-data-init="{ contextMenuHandler: contextMenuHandler, path: pane.path }">{{ pane.title }}</span>
        </template>
      </a-tab-pane>
    </a-tabs>
  </div>
</template>

<script lang="ts">
import Vue from "vue";
import Component from "vue-class-component";
import { Tabs } from "ant-design-vue";
import { Prop, Watch } from "vue-property-decorator";
import { uuidService } from "../../services/uuid.service";
import { Pane } from "../../model/Pane";

@Component({
  name: "BreadcrumbNav",
  components: {
    [Tabs.name]: Tabs,
    [Tabs.TabPane.name]: Tabs.TabPane,
  },
  directives: {
    contextDataInit: {
      inserted: (el: any, binding: any) => {
        el.parentNode.parentNode.addEventListener("contextmenu", function (event: any) {
          binding.value.contextMenuHandler(event, binding.value.path);
        });
      },
    },
  },
})
export default class BreadcrumbNav extends Vue {
  @Prop({ default: false }) enableKeepAlive: boolean | undefined; // 启用组件缓存同步
  @Prop({ default: "params" }) paramsKey: string | undefined; // 缓存key
  activeKey = ""; // 激活面板
  panes: Pane[] = []; // 面包屑列表
  insId: any; // 当前实例

  contextMenuHandler = (event: any, path: string) => {
    this.openContextMenu(event, path);
    event.preventDefault();
  };

  @Watch("$route", { immediate: true })
  onRouteChanged(to: any) {
    if (this.enableKeepAlive) {
      this.syncRemoveKeepAliveIns(to);
    }
    this.navPosition();
  }

  /**
   * @description: 生成当前实例编号
   * @author ChenRui
   * @date 2021/2/8 11:50
   */
  created(): void {
    this.insId = uuidService.getUuid();
  }

  /**
   * @description: 注册当前实例
   * @author ChenRui
   * @date 2021/2/8 11:51
   */
  mounted(): void {
    this.$breadcrumbNavService.ins[this.insId] = this;
  }

  /**
   * @description: 移除当前实例
   * @author ChenRui
   * @date 2021/2/8 11:51
   */
  beforeDestroy(): void {
    delete this.$breadcrumbNavService.ins[this.insId];
  }

  /**
   * @description: 导航定位
   * @author ChenRui
   * @date 2020/12/29 20:23
   */
  navPosition(): void {
    const route = this.$route;
    if (route.path === "/") {
      return;
    }
    let title: string = route.meta && route.meta.name ? route.meta.name : "";
    const nameKey: string = route.meta && route.meta.nameKey ? route.meta.nameKey : "";
    if (!title) {
      if (nameKey) {
        let params: any = {};
        if (route.params && route.params.params && Object.keys(route.params.params).length > 0) {
          params = route.params.params;
        } else {
          params = route.query;
        }
        if (params && params[nameKey]) {
          title = params[nameKey];
        } else {
          return;
        }
      } else {
        return;
      }
    }
    const key = route.path;
    let pane: Pane | undefined = this.panes.find((item: any) => item.key === key);
    if (pane === undefined) {
      pane = { key: key, title: title, path: route.path };
      this.panes.push(pane);
    }
    if (route.params && route.params.params && Object.keys(route.params.params).length > 0) {
      pane.params = route.params.params;
    } else {
      pane.params = route.query;
    }
    this.activeKey = pane.path!;
  }

  /**
   * @description: 面包屑单击处理，根据地质进行页面路由
   * @author ChenRui
   * @date 2020/12/29 20:22
   */
  onTabClick(e: string): void {
    const pane: Pane = this.panes.find((item) => item.key === e) || {};
    if (pane && pane.path != null && pane.path !== "" && pane.path !== this.$route.path) {
      this.$router.push({ path: pane.path, query: pane.params });
    }
  }

  /**
   * @description: 新增面板
   * @author ChenRui
   * @date 2021/2/8 14:27
   */
  add(srcPane: Pane, active = true): void {
    const key: string | undefined = srcPane.path;
    const pane: Pane | undefined = this.panes.find((item) => item.key === key);
    if (pane === undefined) {
      srcPane.title = srcPane.title ? srcPane.title : "尚未设置";
      this.panes.push(srcPane);
    } else {
      pane.title = srcPane.title ? srcPane.title : "尚未设置";
      pane.params = srcPane.params;
    }
    if (active && key) {
      this.activeKey = key;
    }
  }

  /**
   * @description: 同步移除缓存组件实例
   * @author ChenRui
   * @date 2021/6/11 15:11
   */
  syncRemoveKeepAliveIns(route: any): void {
    if (route && route.meta && route.meta.keepAlive && route.matched && route.matched.length > 0) {
      const vnode: any = route.matched[0].instances?.default?.$vnode;
      if (vnode && vnode.parent) {
        const cache: any = vnode.parent.componentInstance.cache || {};
        const keys: any[] = vnode.parent.componentInstance.keys || [];
        keys.forEach((key: any) => {
          if (cache[key] && cache[key].componentInstance && cache[key].componentInstance.$vnode && cache[key].componentInstance.$vnode.data && cache[key].componentInstance.$vnode.data.key) {
            const pane: Pane | undefined = this.panes.find((item) => cache[key].componentInstance.$vnode.data.key === item.path);
            if (pane == null) {
              if (cache[key].componentInstance != null) {
                cache[key].componentInstance.$destroy();
              }
              delete cache[key];
            }
          }
        });
      }
    }
  }

  /**
   * @description: 根据编号删除面包屑导航
   * @author ChenRui
   * @date 2020/12/29 20:22
   */
  remove(targetKey: string, routeToPreviousPage = false) {
    let activeKey: string = this.activeKey;
    // 尝试获取父节点
    const nodes: any[] = this.$routeTopologyService.fetchNodes(targetKey);
    let pane: Pane | undefined;
    if (nodes && nodes.length > 0) {
      for (const node of nodes) {
        pane = this.panes.find((pane) => pane.key === node.path && pane.key !== targetKey);
        if (pane) {
          break;
        }
      }
    }
    // 尝试获取前一个导航节点
    let lastIndex = -1;
    this.panes.forEach((pane, i) => {
      if (pane.key === targetKey) {
        lastIndex = i - 1;
      }
    });
    // 移除目标导航
    const panes: Pane[] = this.panes.filter((pane) => pane.key !== targetKey) || [];
    if (panes.length > 0 && activeKey === targetKey) {
      if (pane) {
        activeKey = pane.key!;
      } else if (lastIndex >= 0) {
        activeKey = panes[lastIndex].key!;
      } else {
        activeKey = panes[0].key!;
      }
    }
    if (panes.length === 0 && nodes && nodes.length > 1) {
      activeKey = nodes[nodes.length - 1].path;
    }
    this.panes = panes;
    if (this.activeKey !== activeKey) {
      if (routeToPreviousPage) {
        const routePane: Pane | undefined = this.panes.find((item) => item.key === activeKey);
        if (routePane != null) {
          this.$router.push({ path: routePane.path, query: routePane.params });
        } else if (activeKey) {
          this.$router.push({ path: activeKey });
        }
      }
      if (this.enableKeepAlive) {
        this.syncRemoveKeepAliveIns(this.$router);
      }
    }
    this.activeKey = activeKey;
  }

  /**
   * @description: 关闭所有
   * @author ChenRui
   * @date 2021/2/8 11:31
   */
  closeAll(path = "/"): void {
    if (path !== this.activeKey) {
      this.$router.push({ path: path });
    }
    setTimeout(() => {
      for (const pane of this.panes) {
        if (!!pane && pane.path && pane.path !== this.activeKey) {
          this.remove(pane.path, true);
        }
      }
    });
  }

  /**
   * @description: 右键菜单
   * @author ChenRui
   * @date 2021/8/9 23:43
   */
  handleRightClick(e: any): void {
    console.log(e);
  }

  /**
   * @description: 打开菜单
   * @author ChenRui
   * @date 2021/2/7 20:20
   */
  openContextMenu(event: any, path: string): void {
    this.$contextmenu({
      items: [
        {
          label: "关闭当前",
          onClick: () => {
            this.remove(path, true);
          },
        },
        {
          label: "关闭其他",
          onClick: () => {
            this.closeAll(path);
          },
        },
        {
          label: "关闭所有",
          onClick: () => {
            this.closeAll();
          },
        },
      ],
      event,
      customClass: "dc-custom-context-menu",
      zIndex: 3,
      minWidth: "initial",
    });
  }
}
</script>

<style scoped lang="scss">
.dc-breadcrumb-nav-view {
  background-color: #ffffff;
  &.dc-breadcrumb-hidden-close {
    ::v-deep {
      .anticon-close {
        display: none;
      }
    }
  }
  ::v-deep {
    .ant-tabs {
      .ant-tabs-bar {
        margin-bottom: 0;
        .ant-tabs-nav-container {
          height: 38px;
          .ant-tabs-nav-wrap {
            margin-top: 7.5px;
            .ant-tabs-nav {
              height: 30px;
              .ant-tabs-tab {
                height: 30px;
                border-color: #137cdd;
                border-bottom: 0;
                line-height: 28px;
              }
            }
          }
        }
      }
    }
  }
  .dc-menu {
  }
}
</style>
