//  Copyright (c) 2024 Huawei Technologies Co., Ltd.
//  openUBMC is licensed under Mulan PSL v2.
//  You can use this software according to the terms and conditions of the Mulan PSL v2.
//  You may obtain a copy of Mulan PSL v2 at:
//        #  http://license.coscl.org.cn/MulanPSL2
//  THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
//  EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
//  MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
//  See the Mulan PSL v2 for more details.
import $http from '@/utils/http-service';
import { nextTick } from 'vue';

/**
 * 功能：触发keepAlive接口的调用（超过10s时）
 * 注册一个全局自定义指令 `v-reqKeepAlive`
 * 因为element-plus的dialog、drawer、tree在点击其内容区域的时候不触发window的点击事件，
 * 导致触发不了会话保持（不调用keepAlive），所以定义自定义指令，为其绑定点击事件，触发keepAlive
 * 注意：
 * 1. v-reqKeepAlive
 * 2. 添加类型修饰符，比如v-reqKeepAlive.dialog
 *    所有的修饰符：dialog（弹窗）、drawer(抽屉)、tree（树）
 * 3. 指令可以直接加到el-tree标签上，但是不能直接加到el-dialog、el-drawer标签上，否则会报警告，且指令绑定失败，需要加在外层
 * 4. el-dialog和el-drawer不能直接挂载在body下，否则自定义指令找不到对应的dom，append-to-body默认是false，不要设置成true
 */
export function reqKeepAliveDerective(app: any) {
  app.directive('reqKeepAlive', {
    mounted(el: any, binding: any) {
      mountedAction(el, binding);
    },
  });
}

function mountedAction(el: any, binding: any) {
  Object.keys(binding.modifiers).forEach(key => {
    switch (key) {
      case 'dialog':
        nextTick(() => {
          action(el, 'el-dialog');
        });
        break;
      case 'drawer':
        nextTick(() => {
          action(el, 'el-drawer');
        });
        break;
      case 'tree':
        nextTick(() => {
          treeAction(el);
          // 当树存在展开项时，展开的时候需要为其单个单元绑定事件
          el.addEventListener('DOMNodeInserted', () => {
            clickAction();
            treeAction(el);
          });
        });
        break;
      default:
        break;
    }
  });
}

// 找到指定类名的子元素
function findAimClassDom(el: any, className: string): any {
  if (el?.children) {
    const children = el.children;
    for (let i = 0; i < children.length; i++) {
      const classList = children[i].classList;
      for (let j = 0; j < classList.length; j++) {
        if (classList[j] === className) {
          return children[i];
        }
      }

      const res = findAimClassDom(children[i], className);
      if (res) {
        return res;
      }
    }
  }
  return null;
}

function action(el: any, className: string) {
  const dom = findAimClassDom(el, className);
  if (dom) {
    dom.addEventListener('click', () => {
      $http.keepAlive('Activate');
    });
  }
}

function clickAction() {
  $http.keepAlive('Activate');
}

// 给el-tree绑定点击事件无效，应该是el-tree给每一个单元加了click.stop，所以这里单独给每一个树的单元绑定点击事件
function treeAction(el: any) {
  let arr: any = [];
  findAimClassDoms(el, 'el-tree-node__content', arr);
  for (let i = 0; i < arr.length; i++) {
    arr[i].removeEventListener('click', clickAction);
    arr[i].addEventListener('click', clickAction);
  }
}

// 找到某个元素下面所有包含指定类名的元素集合
function findAimClassDoms(dom: any, className: string, arr: any) {
  if (dom?.children) {
    const children = dom.children;
    for (let i = 0; i < children.length; i++) {
      const classList = children[i].classList;
      for (let j = 0; j < classList.length; j++) {
        if (classList[j] === className) {
          arr.push(children[i]);
        }
      }

      findAimClassDoms(children[i], className, arr);
    }
  }
}
