import { IPSAppMenu } from '@ibiz/dynamic-model-api';
import { AppServiceBase, AuthServiceBase, LogUtil, MenuControlInterface, Util } from 'ibiz-core';
import { ControlBase } from "./control-base";
import { AppFuncService, NavDataService } from '../app-service';
import { AppMenuService } from "../ctrl-service";

/**
 * 菜单部件基类
 *
 * @export
 * @class AppMenuControlBase
 * @extends {ControlBase}
 */
export class AppMenuControlBase extends ControlBase implements MenuControlInterface {

    /**
     * 菜单部件实例
     * 
     * @memberof AppMenuControlBase
     */
    public controlInstance!: IPSAppMenu;

    /**
     * 部件名称
     * 
     * @memberof AppMenuControlBase
     */
    public name!: string;

    /**
     * 显示处理提示
     * 
     * @memberof AppMenuControlBase
     */
    public showBusyIndicator: boolean = true;

    /**
     * 视图参数
     *
     * @type {*}
     * @memberof AppMenuControlBase
     */
    public viewparams!: any;

    /**
     * 应用上下文
     *
     * @type {*}
     * @memberof AppMenuControlBase
     */
    public context!: any;

    /**
     * 菜单收缩改变
     *
     * @type {boolean}
     * @memberof AppMenuControlBase
     */
    public collapseChange!: boolean;

    /**
     * 当前模式，菜单在顶部还是在底部
     *
     * @type {*}
     * @memberof AppMenuControlBase
     */
    public mode!: string;

    /**
     * 当前选中主题
     *
     * @type {*}
     * @memberof AppMenuControlBase
     */
    public selectTheme!: string;

    /**
     * 默认激活的index
     *
     * @type {*}
     * @memberof AppMenuControlBase
     */
    public defaultActive: any = null;

    /**
     * 触发方式，默认click
     *
     * @type {string}
     * @memberof AppMenuControlBase
     */
    public trigger: string = 'click';

    /**
     * 默认打开的index数组
     *
     * @type {any[]}
     * @memberof AppMenuControlBase
     */
    public defaultOpeneds: any[] = [];

    /**
     * 是否计算好默认打开项
     */
    public isDefaultOpenedsReady: boolean = false;

    /**
     * 应用起始页面
     *
     * @type {boolean}
     * @memberof AppMenuControlBase
     */
    public isDefaultPage: boolean = false;

    /**
     * 空白视图模式
     *
     * @type {boolean}
     * @memberof AppMenuControlBase
     */
    public isBlankMode: boolean = false;

    /**
     * 应用导航服务
     *
     * @type {*}
     * @memberof AppMenuControlBase
     */
    public navDataService: NavDataService = NavDataService.getInstance(this.$store);

    /**
     * 默认打开视图
     *
     * @type {boolean}
     * @memberof AppMenuControlBase
     */
    public defPSAppView: any;

    /**
     * 计数器数据
     *
     * @type {*}
     * @memberof AppMenuControlBase
     */
    public counterdata: any;

    /**
     * 菜单模型
     *
     * @public
     * @type 
     * @memberof AppMenuControlBase
     */
    public menuMode: any;

    /**
     * 菜单数据
     *
     * @public
     * @type {any[]}
     * @memberof AppMenuControlBase
     */
    public menus: any[] = [];

    /**
     * 建构权限服务对象
     *
     * @type {AuthService}
     * @memberof AppMenuControlBase
     */
    public authService!: AuthServiceBase;

    /**
     * 是否需要使用计数器
     *
     * @private
     * @type {boolean}
     * @memberof AppMenuControlBase
     */
    private needUseCounter: boolean = false;

    /**
     * 微应用状态订阅对象
     *
     * @private
     * @type {*}
     * @memberof AppMenuControlBase
     */
    private MicroAppStateEvent: any;

    /**
     * 当前应用是否为微应用
     *
     * @memberof AppMenuControlBase
     */
    public isMicroApp: boolean = false;

    /**
     * 提示框主题样式
     *
     * @type {string}
     * @memberof AppMenuControlBase
     */
    public popperClass(): string {
        return 'app-popper-menu ' + this.selectTheme;
    }

    /**
     * 监听部件动态参数变化
     *
     * @param {*} newVal
     * @param {*} oldVal
     * @memberof AppMenuControlBase
     */
    public onDynamicPropsChange(newVal: any, oldVal: any) {
        super.onDynamicPropsChange(newVal, oldVal);
        this.collapseChange = newVal.collapseChange;
        this.$forceUpdate();
    }

    /**
     * 监听部件参数变化
     *
     * @param {*} newVal
     * @param {*} oldVal
     * @memberof AppMenuControlBase
     */
    public onStaticPropsChange(newVal: any, oldVal: any) {
        this.mode = newVal.mode ? newVal.mode : 'LEFT';
        this.selectTheme = newVal.selectTheme;
        this.isDefaultPage = newVal.isDefaultPage ? newVal.isDefaultPage : this.isDefaultPage;
        this.isBlankMode = newVal.isBlankMode ? newVal.isBlankMode : this.isBlankMode;
        this.defPSAppView = newVal.defPSAppView;
        this.counterdata = newVal.counterdata;
        super.onStaticPropsChange(newVal, oldVal)
    }

    /**
     * 部件模型数据初始化
     *
     * @memberof AppMenuControlBase
     */
    public async ctrlModelInit(args?: any) {
        await super.ctrlModelInit();
        this.service = new AppMenuService(this.controlInstance, this.context);
        await this.service.initServiceParam(this.context, this.controlInstance);
        const microAppService = AppServiceBase.getInstance().getMicroAppService();
        if (microAppService) {
            this.isMicroApp = microAppService.getIsMicroApp();
            if (microAppService.getAppState()) {
                this.MicroAppStateEvent = microAppService.getAppState().subscribe((state: any) => {
                    const { tag, action, data } = state;
                    if (Object.is(tag, this.Environment.microAppName)) {
                        if (Object.is(action, 'MENUCLICK')) {
                            const appFuncs: Array<any> = this.service.getAllFuncs();
                            const appFunc = appFuncs.find((element: any) => {
                                return element.appfunctag === data?.funtag;
                            });
                            if (appFunc) {
                                AppFuncService.getInstance().executeApplication(appFunc, Util.deepCopy(this.context));
                            }
                        }
                    }
                })
            }
        }
    }

    /**
     * 应用菜单初始化
     *
     * @memberof AppMenuControlBase
     */
    public ctrlInit(args?: any) {
        super.ctrlInit();
        let _this: any = this;
        this.authService = new AuthServiceBase({ $store: _this.$store })
        if (this.viewState) {
            this.viewStateEvent = this.viewState.subscribe(({ tag, action, data }: any) => {
                if (!Object.is(tag, this.name)) {
                    return;
                }
                this.load();
            });
        }
    }

    /**
     * 部件销毁
     *
     * @memberof AppMenuControlBase
     */
    public ctrlDestroyed(args?: any) {
        super.ctrlDestroyed(args);
        if (this.MicroAppStateEvent) {
            this.MicroAppStateEvent.unsubscribe();
        }
    }

    /**
     * 数据加载
     *  
     * @memberof AppMenuControlBase
     */
    public load() {
        this.handleMenusResource(this.service.getAllMenuItems());
    }

    /**
     * 菜单项选中处理
     *
     * @param {menuName } 选中菜单名称
     * @returns
     * @memberof AppMenuControlBase
     */
    public select(menuName: any) {
        let item = this.compute(this.menus, menuName);
        if (Object.keys(item).length === 0) {
            return;
        }
        this.click(item);
    }

    /**
     * 处理菜单默认选中项
     *
     * @public
     * @memberof AppMenuControlBase
     */
    public defaultMenuSelect(): void {
        if (!this.isDefaultPage || this.isBlankMode) {
            return;
        }
        const appFuncs: Array<any> = this.service.getAllFuncs();
        if (this.$route && this.$route.matched && this.$route.matched.length == 2) { // 存在二级路由
            const [{ }, matched] = this.$route.matched;
            const appfunc: any = appFuncs?.find((_appfunc: any) => Object.is(_appfunc.routepath, matched.path) && Object.is(_appfunc.appfunctype, 'APPVIEW'));
            if (appfunc) {
                this.computeMenuSelect(this.menus, appfunc.appfunctag);
                this.isDefaultOpenedsReady = true;
            }
            return;
        } else if (this.defPSAppView && Object.keys(this.defPSAppView).length > 0) { // 存在默认视图
            const appfunc: any = appFuncs?.find((_appfunc: any) => Object.is(_appfunc.routepath, this.defPSAppView.routepath) && Object.is(_appfunc.appfunctype, 'APPVIEW'));
            if (appfunc) {
                this.computeMenuSelect(this.menus, appfunc.appfunctag);
                this.isDefaultOpenedsReady = true;
            }
            const viewparam: any = {};
            const path: string = this.$viewTool.buildUpRoutePath(this.$route, {}, this.defPSAppView.deResParameters, this.defPSAppView.parameters, [], viewparam);
            this.$router.push(path);
            return;
        }
        this.computeMenuSelect(this.menus, '');
        this.isDefaultOpenedsReady = true;
        let item = this.compute(this.menus, this.defaultActive);
        if (Object.keys(item).length === 0) {
            return;
        }
        if (!item.hidden) {
            this.click(item);
        }
    }

    /**
     * 计算菜单选中项
     *
     * @public
     * @param {Array<any>} items 菜单数据
     * @param {string} appfunctag 应用功能tag
     * @return {*}  {boolean}
     * @memberof AppMenuControlBase
     */
    public computeMenuSelect(items: Array<any>, appfunctag: string): boolean {
        const appFuncs: Array<any> = this.service.getAllFuncs();
        const result = items.some((item: any) => {
            if (Object.is(appfunctag, '') && item.getPSAppFunc && item.openDefault && !item.hidden) {
                const appfunc = appFuncs?.find((_appfunc: any) => Object.is(_appfunc.appfunctag, item.getPSAppFunc.codeName));
                if (appfunc) {
                    this.defaultActive = item.name;
                    this.setHideSideBar(item);
                    return true;
                }
            }
            if (item.getPSAppFunc && Object.is(item.getPSAppFunc.codeName, appfunctag)) {
                this.setHideSideBar(item);
                this.defaultActive = item.name;
                return true;
            }
            if (item.getPSAppMenuItems && item.getPSAppMenuItems.length > 0) {
                const state = this.computeMenuSelect(item.getPSAppMenuItems, appfunctag);
                if (state) {
                    this.defaultOpeneds.push(item.name);
                    return true;
                }
            }
            return false;
        });
        return result;
    }

    /**
     * 获取菜单项数据
     *
     * @public
     * @param {any[]} items
     * @param {string} name
     * @returns
     * @memberof AppMenuControlBase
     */
    public compute(items: any[], name: string) {
        const item: any = {};
        items.some((_item: any) => {
            if (name && Object.is(_item.name, name)) {
                Object.assign(item, _item);
                this.setHideSideBar(_item);
                return true;
            }
            if (_item.getPSAppMenuItems && Array.isArray(_item.getPSAppMenuItems)) {
                const subItem = this.compute(_item.getPSAppMenuItems, name);
                if (Object.keys(subItem).length > 0) {
                    Object.assign(item, subItem);
                    return true;
                }
            }
            return false;
        });
        return item;
    }

    /**
     * 设置是否隐藏菜单栏
     *
     * @public
     * @param {*} item
     * @memberof AppMenuControlBase
     */
    public setHideSideBar(item: any): void {
        if (this.isDefaultPage && item.hidesidebar) {
            this.$emit('collapsechange', true);
        }
    }

    /**
     * 菜单点击
     *  
     * @param {*} item 点击项
     * @memberof AppMenuControlBase
     */
    public click(item: any) {
        if (Object.is((this.controlInstance as any)?.parentModel?.viewStyle, 'STYLE4') && (!this.mode || Object.is(this.mode, 'LEFT'))) {
            this.$store.commit('removeAllPage');
            this.navDataService.removeNavDataFrist();
        }
        let tempContext: any = Util.deepCopy(this.context);
        if (item.getPSNavigateContexts) {
            const localContext = Util.formatNavParam(item.getPSNavigateContexts);
            Object.assign(tempContext, localContext);
        } else {
            if (tempContext.hasOwnProperty("srfdynainstid")) {
                delete tempContext.srfdynainstid;
            }
        }
        if (item.getPSAppFunc) {
            const appFuncs: Array<any> = this.service.getAllFuncs();
            const appFunc = appFuncs.find((element: any) => {
                return element.appfunctag === item.getPSAppFunc.codeName;
            });
            if (appFunc) {
                AppFuncService.getInstance().executeApplication(appFunc, tempContext);
            }
        } else {
            LogUtil.warn(this.$t('app.commonwords.noassign'));
        }
    }

    /**
     * 通过统一资源标识计算菜单
     *
     * @param {*} data
     * @memberof AppMenuControlBase
     */
    public handleMenusResource(inputMenus: Array<any>) {
        let _this: any = this;
        if (_this.$store.getters['authresource/getEnablePermissionValid']) {
            this.computedEffectiveMenus(inputMenus);
            //  不使用计数器则抛出事件让视图销毁计数器
            if (!this.needUseCounter) {
                this.ctrlEvent({ controlname: this.name, action: 'destoryCounter', data: null });
            }
            // this.computeParentMenus(inputMenus);
        }
        this.dataProcess(inputMenus);
        this.isDefaultOpenedsReady = true;
        this.menus = inputMenus;
        if(!this.isMicroApp){
            this.defaultMenuSelect();
        }
    }

    /**
     * 计算有效菜单项
     *
     * @param {*} inputMenus
     * @memberof AppMenuControlBase
     */
    public computedEffectiveMenus(inputMenus: Array<any>) {
        inputMenus.forEach((_item: any) => {
            //  无权限
            if (!this.authService.getMenusPermission(_item)) {
                _item.hidden = true;
            } else {
                if (Util.isExistAndNotEmpty(_item.counterid)) {
                    this.needUseCounter = true;
                }
            }
            //  父隐藏时不计算子权限
            if (_item.getPSAppMenuItems && _item.getPSAppMenuItems.length > 0 && !_item.hidden) {
                this.computedEffectiveMenus(_item.getPSAppMenuItems);
            }
        })
    }

    // /**
    //  * 计算父项菜单项是否隐藏
    //  *
    //  * @param {*} inputMenus
    //  * @memberof AppMenuControlBase
    //  */
    // public computeParentMenus(inputMenus:Array<any>){
    //     if(inputMenus && inputMenus.length >0){
    //         inputMenus.forEach((item:any) =>{
    //             if(item.hidden && item.getPSAppMenuItems && item.getPSAppMenuItems.length >0){
    //                 item.getPSAppMenuItems.map((singleItem:any) =>{
    //                     if(!singleItem.hidden){
    //                         item.hidden = false;
    //                     }else{
    //                         if(singleItem.getPSAppMenuItems && singleItem.getPSAppMenuItems.length >0){
    //                             singleItem.getPSAppMenuItems.map((grandsonItem:any) =>{
    //                                 if(!grandsonItem.hidden){
    //                                     item.hidden = false;
    //                                 }
    //                             })
    //                         }
    //                     }
    //                     if(item.getPSAppMenuItems && item.getPSAppMenuItems.length >0){
    //                         this.computeParentMenus(item.getPSAppMenuItems);
    //                     }
    //                 })
    //             }
    //         })
    //     }
    // }

    /**
     * 数据处理
     *
     * @public
     * @param {any[]} items
     * @memberof AppMenuControlBase
     */
    public dataProcess(items: any[]): void {
        items.forEach((_item: any) => {
            if (_item.expanded) {
                this.defaultOpeneds.push(_item.name);
            }
            if (_item.getPSAppMenuItems && _item.getPSAppMenuItems.length > 0) {
                this.dataProcess(_item.getPSAppMenuItems)
            }
        });
    }

    /**
     * @description 处理关闭菜单
     * @param {*} key 菜单项标识
     * @param {*} keyPath 标识集合
     * @memberof AppMenuControlBase
     */
    public handleCloseMenu(key: any, keyPath: any) {
        const refs: any = this.$refs;
        if (refs[this.controlInstance?.codeName] && refs[this.controlInstance?.codeName].close instanceof Function) {
            refs[this.controlInstance?.codeName].close(key);
        }
    }
}