import { ref, unref, onBeforeMount, onBeforeUnmount } from 'vue';
import { useDebounceFn } from '@vueuse/core';
import { cloneDeep } from 'lodash-es';

interface SearchResult {
    name: string;//名称
    path: string;//跳转路径
    icon: string;//图标
    meta?: any
    children?: any
}

interface TreeHelperConfig {
    id: string;
    children: string;
    pid: string;
}

// 默认配置
const DEFAULT_CONFIG: TreeHelperConfig = {
    id: 'id',
    children: 'children',
    pid: 'pid',
};

// 获取配置。  Object.assign 从一个或多个源对象复制到目标对象
const getConfig = (config: Partial<TreeHelperConfig>) => Object.assign({}, DEFAULT_CONFIG, config);


export function useMenuSearch(mstore, useRouter, inputSearchRef) {
    const { push } = useRouter();
    const searchResult = ref<SearchResult[]>([]);
    const inputSearch = ref<string>('')
    const isMouseenter = ref()
    // 菜单列表
    let menuList: any[] = [];

    function transform(c: string) {
        const code: string[] = ['$', '(', ')', '*', '+', '.', '[', ']', '?', '\\', '^', '{', '}', '|'];
        return code.includes(c) ? `\\${c}` : c;
    }

    function createSearchReg(key: string) {
        const keys = [...key].map((item) => transform(item));
        const str = ['', ...keys, ''].join('.*');
        return new RegExp(str);
    }

    function filter<T = any>(
        tree: T[],
        func: (n: T) => boolean,
        config: Partial<TreeHelperConfig> = {},
    ): T[] {
        // 获取配置
        config = getConfig(config);
        const children = config.children as string;

        function listFilter(list: T[]) {
            return list
                .map((node: any) => ({ ...node }))
                .filter((node) => {
                    // 递归调用 对含有children项  进行再次调用自身函数 listFilter
                    node[children] = node[children] && listFilter(node[children]);
                    // 执行传入的回调 func 进行过滤
                    return func(node) || (node[children] && node[children].length);
                });
        }

        return listFilter(tree);
    }

    // 扁平化数组-只对最后一层合并
    function treeToArray(tree) {
        return tree.reduce((res, item) => {
            const { children, ...i } = item
            return res.concat(children && children.length ? treeToArray(children) : i)
        }, [])
    }

    // 获取菜单数据
    onBeforeMount(() => {
        menuList = cloneDeep(mstore.menuList);
        window.addEventListener("keyup", keyupSearch)
    });

    onBeforeUnmount(() => {
        // 销毁事件
        window.removeEventListener("keyup", keyupSearch)
    })

    // 回车事件
    function keyupSearch(e) {
        if (e.keyCode === 13 && searchResult.value.length > 0) {
            inputSearch.value.indexOf('/') !== -1 ? goView(inputSearch.value) : goView(searchResult.value[0].path)
        }
    }

    // 搜索
    function search(val: string) {
        const key = val.trim();
        inputSearch.value = key;
        if (!key) {
            searchResult.value = [];
            return;
        }
        const reg = createSearchReg(unref(inputSearch));
        const filterMenu = handlerSearchResult(menuList, reg);
        searchResult.value = treeToArray(filterMenu).filter(item => item.meta.title.indexOf(unref(inputSearch)) !== -1);
    }

    // 使用防抖事件
    const handleSearch = useDebounceFn(search, 500);
    // const onMouseLeave = useDebounceFn(mouseLeave, 1000);

    // 过滤的列表
    function handlerSearchResult(menuList: SearchResult[], reg: RegExp) {
        return filter(menuList, (item) => {
            return reg.test(item.meta.title);
        });
    }

    // 清空
    const clearData = () => {
        searchResult.value = [];
        inputSearch.value = "";
    }

    // 移入事件
    function onMouseenter() {
        clearTimeout(isMouseenter.value)
        inputSearchRef.value.focus()
    }

    // 移出事件
    function onMouseLeave() {
        isMouseenter.value = setTimeout(() => {
            inputSearchRef.value.blur()
        }, 500)
    }

    // 点击跳转
    const goView = (path: string) => {
        push(path)
        clearData()
    }


    return {
        handleSearch,
        goView,
        onMouseenter,
        onMouseLeave,
        inputSearch,
        searchResult
    }
}