import { IPSAppDataEntity, IPSAppDEMultiDataView, IPSControlNavigatable, IPSDECalendar, IPSDETBUIActionItem, IPSDEToolbar, IPSDEToolbarItem, IPSDETree, IPSDEUIAction, IPSExpBar, IPSSysImage, IPSLanguageRes, IPSSysMap, IPSDEChart, IPSAppDERedirectView, IPSAppView, IPSNavigateContext, IPSNavigateParam, IPSAppViewRef } from '@ibiz/dynamic-model-api';
import { throttle, ExpBarControlInterface, ModelTool, Util, ViewTool, IParams, StringUtil, AppServiceBase } from 'ibiz-core';
import { Subscription } from 'rxjs';
import { AppGlobalService, AppViewLogicService } from '../app-service';
import { MainControlBase } from './main-control-base';

/**
 * 导航栏部件基类
 *
 * @export
 * @class ExpBarControlBase
 * @extends {MainControlBase}
 */
export class ExpBarControlBase extends MainControlBase implements ExpBarControlInterface {
    /**
     * 导航栏部件模型对象
     *
     * @memberof ExpBarControlBase
     */
    public declare controlInstance: IPSExpBar;

    /**
     * 数据部件
     *
     * @memberof ExpBarControlBase
     */
    protected $xDataControl!: IPSDECalendar | IPSControlNavigatable | IPSDETree | IPSSysMap | IPSDEChart;

    /**
     * 父导航视图模型对象
     *
     * @memberof ExpBarControlBase
     */
    protected parentModel!: IPSAppDEMultiDataView;

    /**
     * 数据部件名称
     *
     * @memberof ExpBarControlBase
     */
    public xDataControlName!: string;

    /**
     * 视图唯一标识
     *
     * @type {boolean}
     * @memberof ExpBarControlBase
     */
    public viewUID: string = '';

    /**
     * 搜素值
     *
     * @type {(string)}
     * @memberof ExpBarControlBase
     */
    public searchText: string = '';

    /**
     * 导航视图名称
     *
     * @type {*}
     * @memberof ExpBarControlBase
     */
    public navViewName: any = {};

    /**
     * 导航视图模型
     *
     * @type {*}
     * @memberof ExpBarControlBase
     */
    public navViewModel: IPSAppView | null = null;

    /**
     * 导航参数
     *
     * @type {*}
     * @memberof ExpBarControlBase
     */
    public navParam: any = {};

    /**
     * 导航上下文参数
     *
     * @type {*}
     * @memberof ExpBarControlBase
     */
    public navigateContext: any = {};

    /**
     * 导航视图参数
     *
     * @type {*}
     * @memberof ExpBarControlBase
     */
    public navigateParams: any = {};

    /**
     * 导航过滤项
     *
     * @type {string}
     * @memberof ExpBarControlBase
     */
    public navFilter: string = "";

    /**
     * 导航关系
     *
     * @type {string}
     * @memberof ExpBarControlBase
     */
    public navPSDer: string = "";

    /**
     * 选中数据
     *
     * @type {*}
     * @memberof ExpBarControlBase
     */
    public selection: any = {};

    /**
     * 工具栏模型数据
     *
     * @protected
     * @type {*}
     * @memberof ExpBarControlBase
     */
    protected toolbarModels: any;

    /**
     * 缓存UUID
     * (导航部件抛出值时,renderNavView创建视图容器需要UUID来创建一个新的,才能重绘刷新右侧)
     * 
     * 
     * @type {*}
     * @memberof ExpBarControlBase
     */
    public cacheUUID: any;

    /**
     * @description 导航栏部件事件
     * @type {(Subscription | undefined)}
     * @memberof ExpBarControlBase
     */
    public expbarControlEvent: Subscription | undefined;

    /**
     * 监听静态参数变化
     *
     * @param {*} newVal
     * @param {*} oldVal
     * @memberof ExpBarControlBase
     */
    public onStaticPropsChange(newVal: any, oldVal: any) {
        this.viewUID = newVal.viewUID;
        super.onStaticPropsChange(newVal, oldVal);
    }

    /**
     * 部件模型数据初始化实例
     *
     * @memberof ExpBarControlBase
     */
    public async ctrlModelInit(args?: any) {
        await super.ctrlModelInit();
        this.xDataControlName = this.controlInstance.xDataControlName;
        this.$xDataControl = ModelTool.findPSControlByName(this.xDataControlName, this.controlInstance.getPSControls());
        this.showBusyIndicator = this.controlInstance?.showBusyIndicator;
        this.navigateContext = null;
        this.navigateParams = null;
        await this.handleXDataCtrlOptions();
    }

    /**
     * 处理数据部件参数
     *
     * @memberof ExpBarControlBase
     */
    public async handleXDataCtrlOptions() { }

    /**
     * 获取重定向视图模型路径
     *
     * @param {IParams} tempContext
     * @param {IParams} tempViewParams
     * @param {IPSAppDERedirectView} redirectView
     * @memberof ExpBarControlBase
     */
    public async getRedirectViewModelPath(tempContext: IParams, tempViewParams: IParams, redirectView: IPSAppDERedirectView): Promise<any> {
        let localParams: any = {};
        if (tempViewParams && tempViewParams.srfwf) {
            localParams = { srfwf: tempViewParams.srfwf.toLowerCase() };
        }
        const response = await this.getRDAppView(tempContext, localParams, redirectView);
        let targetOpenViewRef: IPSAppViewRef | null = ViewTool.computeRedirectViewRef(
            redirectView,
            localParams,
            response,
        );
        if (!targetOpenViewRef) {
            return;
        }
        //  导航上下文
        if (
            targetOpenViewRef.getPSNavigateContexts() &&
            (targetOpenViewRef.getPSNavigateContexts() as IPSNavigateContext[]).length > 0
        ) {
            let localContextRef: any = Util.formatNavParam(targetOpenViewRef.getPSNavigateContexts(), true);
            let _context: any = Util.computedNavData(response, tempContext, tempViewParams, localContextRef);
            //  填充字符串数据
            if (_context && Object.keys(_context).length > 0) {
                for (const key of Object.keys(_context)) {
                    _context[key] = StringUtil.fillStrData(_context[key], tempContext, response);
                }
            }
            Object.assign(tempContext, _context);
        }
        //  导航视图参数
        if (
            targetOpenViewRef.getPSNavigateParams() &&
            (targetOpenViewRef.getPSNavigateParams() as IPSNavigateParam[]).length > 0
        ) {
            let localViewParamsRef: any = Util.formatNavParam(targetOpenViewRef.getPSNavigateParams(), true);
            let _viewParams: any = Util.computedNavData(response, tempContext, tempViewParams, localViewParamsRef);
            //  填充字符串数据
            if (_viewParams && Object.keys(_viewParams).length > 0) {
                for (const key of Object.keys(_viewParams)) {
                    _viewParams[key] = StringUtil.fillStrData(_viewParams[key], tempContext, response);
                }
            }
            Object.assign(tempViewParams, _viewParams);
        }
        if (targetOpenViewRef.getRefPSAppView()) {
            let targetOpenView: IPSAppView | null = targetOpenViewRef.getRefPSAppView();
            if (!targetOpenView) {
                return;
            }
            await targetOpenView.fill(true);
            if (targetOpenView.modelPath) {
                return { tempContext, tempViewParams, modelPath: targetOpenView.modelPath };
            }
        }
    };

    /**
     * 获取重定向视图
     *
     * @param {IParams} context
     * @param {IParams} viewParams
     * @param {IPSAppDERedirectView} redirectView
     * @return {*} 
     * @memberof ExpBarControlBase
     */
    public async getRDAppView(context: IParams, viewParams: IParams, redirectView: IPSAppDERedirectView) {
        let dataSetParams: any = {};
        if (redirectView.enableCustomGetDataAction) {
            const action = redirectView.getGetDataPSAppDEAction();
            const filed = redirectView.getTypePSAppDEField();
            if (action) {
                Object.assign(dataSetParams, {
                    action: action.codeName,
                });
            }
            if (filed) {
                Object.assign(dataSetParams, {
                    type: filed.codeName.toLowerCase(),
                });
            }
        }
        if (this.appUIService) {
            const response = await this.appUIService.getRDAppView(context, viewParams, {}, dataSetParams);
            return response;
        }
    }

    /**
     * 部件初始化
     *
     * @param {*} [args]
     * @memberof ExpBarControlBase
     */
    public ctrlInit(args?: any) {
        super.ctrlInit(args);
        this.initCtrlToolBar();
        if (this.viewState) {
            this.expbarControlEvent = this.viewState.subscribe(({ tag, action, data }: any) => {
                if (!Object.is(tag, this.name)) {
                    return;
                }
                if (this.$xDataControl) {
                    this.viewState.next({ tag: this.xDataControlName, action: action, data: data });
                }
            });
        }
    }

    /**
     * @description 计算导航区工具栏状态
     * @param {boolean} state 状态值
     * @param {*} [data] 选中数据
     * @memberof ExpBarControlBase
     */
    public calcNavigationToolbarState(state: boolean, data?: any) {
        ViewTool.calcToolbarItemState(state, this.toolbarModels);
        ViewTool.calcToolbarItemAuthState(data, this.toolbarModels, this.appUIService);
    }

    /**
     * 初始化工具栏数据
     * 
     * @memberof ExpBarControlBase
     */
    public initCtrlToolBar() {
        let targetViewToolbarItems: any[] = [];
        const toolbar: IPSDEToolbar = ModelTool.findPSControlByType("TOOLBAR", this.controlInstance.getPSControls() || []) as IPSDEToolbar;
        if (toolbar) {
            const toolbarItems: Array<IPSDEToolbarItem> = toolbar.getPSDEToolbarItems() || [];
            toolbarItems.forEach((item: IPSDEToolbarItem) => {
                const img = item.getPSSysImage();
                const css = item.getPSSysCss();
                let itemModel: any = {
                    name: item.name,
                    showCaption: item.showCaption,
                    showIcon: item.showIcon,
                    tooltip: this.$tl((item.getTooltipPSLanguageRes() as IPSLanguageRes)?.lanResTag, item.tooltip),
                    iconcls: (item.getPSSysImage() as IPSSysImage)?.cssClass,
                    icon: (item.getPSSysImage() as IPSSysImage)?.glyph,
                    caption: this.$tl((item.getCapPSLanguageRes() as IPSLanguageRes)?.lanResTag, item.caption),
                    disabled: false,
                    itemType: item.itemType,
                    visabled: true,
                    getPSSysImage: img ? { cssClass: img.cssClass, imagePath: img.imagePath } : '',
                };
                if (item.itemType && item.itemType == "DEUIACTION") {
                    const uiAction: IPSDEUIAction = (item as IPSDETBUIActionItem).getPSUIAction() as IPSDEUIAction;
                    Object.assign(itemModel, {
                        actiontarget: (item as IPSDETBUIActionItem).uIActionTarget,
                        noprivdisplaymode: (item as IPSDETBUIActionItem).noPrivDisplayMode,
                        dataaccaction: uiAction?.dataAccessAction,
                        uiaction: {
                            tag: uiAction?.uIActionTag,
                            actionTarget: uiAction?.actionTarget,
                        }
                    });
                }
                targetViewToolbarItems.push(itemModel);
            })
        }
        this.toolbarModels = targetViewToolbarItems;
    }

    /**
     * 初始化导航参数
     * 
     * @param params 初始化参数
     * @memberof ExpBarControlBase
     */
    public initNavParam(params: any) {
        if (params && params.length > 0) {
            let navParams: any = {};
            params.forEach((param: any) => {
                const navParam = {
                    [param.key]: param.rawValue ? param.value : "%" + param.value + "%",
                }
                Object.assign(navParams, navParam);
            });
            return navParams;
        } else {
            return null;
        }
    }

    /**
     * 初始化部件的绘制参数
     *
     * @type {Array<*>}
     * @memberof ViewBase
     */
    public initRenderOptions(opts?: any) {
        this.renderOptions = {};
        const { controlType, codeName } = this.controlInstance;
        // 部件类名
        const controlClassNames: any = {
            'control-container': true,
            'app-control-expbar': true,
            [`app-control-${controlType.toLowerCase()}`]: true,
            [Util.srfFilePath2(codeName)]: true,
        };
        Object.assign(controlClassNames, opts);
        if (this.controlInstance?.getPSSysCss?.()?.cssName) {
            Object.assign(controlClassNames, { [this.controlInstance.getPSSysCss()?.cssName || '']: true });
        }
        const quickGroupSearch = this.$parent.$slots?.['quickGroupSearch'];
        if ((!quickGroupSearch && !this.controlInstance.showTitleBar && !this.controlInstance.enableSearch && !(this.toolbarModels && this.toolbarModels.length))) {
            Object.assign(controlClassNames, { 'app-control-expbar--noheader': true });
        }
        this.$set(this.renderOptions, 'controlClassNames', controlClassNames);
    }

    /**
     * 绘制数据部件
     *
     * @memberof ExpBarControlBase
     */
    public renderXDataControl() {
        let { targetCtrlName, targetCtrlParam, targetCtrlEvent } = this.computeTargetCtrlData(this.$xDataControl);
        Object.assign(targetCtrlParam.staticProps, {
            isSelectFirstDefault: true,
            isSingleSelect: true
        });
        return this.$createElement(targetCtrlName, { key: this.xDataControlName, props: targetCtrlParam, ref: this.xDataControlName, on: targetCtrlEvent });
    }

    /**
     * 绘制工具栏
     * 
     * @memberof ExpBarControlBase
     */
    public renderToolbar() {
        return (<view-toolbar slot='toolbar' toolbarModels={this.toolbarModels} counterServiceArray={this.counterServiceArray} on-item-click={(data: any, $event: any) => { throttle(this.handleItemClick, [data, $event], this) }}></view-toolbar>);
    }

    /**
     * 工具栏点击
     * 
     * @param {*} data 事件数据
     * @param {*} $event 事件对象
     * @return {*} 
     * @memberof ExpBarControlBase
     */
    public handleItemClick(data: any, $event: any) {
        if (this.Environment && this.Environment.isPreviewMode) {
            return;
        }
        if (AppServiceBase.getInstance().getEnableUIModelEx()) {
            const toolbar: IPSDEToolbar = ModelTool.findPSControlByType("TOOLBAR", this.controlInstance.getPSControls() || []) as IPSDEToolbar;
            const uiAction = ModelTool.getToolBarUIActionByItemName(toolbar, data.tag);
            const actionParam = { xDataControlName: this.xDataControlName, entityName: this.appDeCodeName.toLowerCase() };
            AppGlobalService.getInstance().executeGlobalUIAction(uiAction, $event, this, actionParam);
        } else {
            AppViewLogicService.getInstance().executeViewLogic(`${this.controlInstance.name?.toLowerCase()}_toolbar_${data.tag}_click`, $event, this, undefined, this.controlInstance.getPSAppViewLogics() || []);
        }
    }

    /**
     * 刷新
     *
     * @memberof ExpBarControlBase
     */
    public refresh(): void {
        if (this.$xDataControl) {
            const xDataControl: any = (this.$refs[`${(this.xDataControlName)?.toLowerCase()}`] as any).ctrl;
            if (xDataControl && xDataControl.refresh && xDataControl.refresh instanceof Function) {
                xDataControl.refresh();
            }
        }
    }

    /**
     * 选中数据事件
     * 
     *
     * @param {any[]} args 选中数据
     * @return {*}  {Promise<void>}
     * @memberof ExpBarControlBase
     */
    public async onSelectionChange(args: any[]): Promise<void> {
        let tempContext: any = {};
        let tempViewParam: any = {};
        if (args.length === 0) {
            this.calcNavigationToolbarState(true);
            return;
        }
        const arg: any = args[0];
        if (this.context) {
            Object.assign(tempContext, Util.deepCopy(this.context));
        }
        if (this.$xDataControl) {
            const appDataEntity: IPSAppDataEntity | null = this.$xDataControl?.getPSAppDataEntity();
            if (appDataEntity) {
                Object.assign(tempContext, { [`${appDataEntity.codeName?.toLowerCase()}`]: arg[appDataEntity.codeName?.toLowerCase()] });
                Object.assign(tempContext, { srfparentdename: appDataEntity.codeName, srfparentdemapname: (appDataEntity as any)?.getPSDEName(), srfparentkey: arg[appDataEntity.codeName?.toLowerCase()] });
                if (this.navFilter && !Object.is(this.navFilter, "")) {
                    Object.assign(tempViewParam, { [this.navFilter]: arg[appDataEntity.codeName?.toLowerCase()] });
                }
                if (this.navPSDer && !Object.is(this.navPSDer, "")) {
                    Object.assign(tempViewParam, { [this.navPSDer]: arg[appDataEntity.codeName?.toLowerCase()] });
                }
            }
            if (this.navigateContext && Object.keys(this.navigateContext).length > 0) {
                let _context: any = this.$util.computedNavData(arg, tempContext, tempViewParam, this.navigateContext);
                Object.assign(tempContext, _context);
            }
            if (this.navigateParams && Object.keys(this.navigateParams).length > 0) {
                let _params: any = this.$util.computedNavData(arg, tempContext, tempViewParam, this.navigateParams);
                Object.assign(tempViewParam, _params);
            }
            if (this.navViewModel) {
                if (Object.is(this.navViewModel.viewType, 'DEREDIRECTVIEW')) {
                    const { modelPath } = await this.getRedirectViewModelPath(tempContext, tempViewParam, this.navViewModel as IPSAppDERedirectView);
                    Object.assign(tempContext, { viewpath: modelPath });
                } else {
                    Object.assign(tempContext, { viewpath: this.navViewModel.modelPath });
                }
            }
            this.handleCtrlEvents('onselectionchange', { action: 'selectionchange', data: args }).then((res: boolean) => {
                if (res) {
                    const params = {
                        data: args,
                        srfnavdata: {
                            context: tempContext,
                            viewparams: tempViewParam
                        }
                    }
                    const key: any = this.$xDataControl?.getPSAppDataEntity()?.codeName.toLowerCase();
                    this.calcNavigationToolbarState(arg && key && arg[key] ? false : true, arg);
                    this.$emit("ctrl-event", { controlname: this.controlInstance.name, action: "selectionchange", data: params });
                }
            })
        } else {
            this.calcNavigationToolbarState(true);
            return;
        }
    }

    /**
     * load完成事件
     * 
     * @param {*} args 加载数据
     * @param {string} [tag]
     * @param {*} [$event2]
     * @memberof ExpBarControlBase
     */
    public onLoad(args: any, tag?: string, $event2?: any) {
        this.calcNavigationToolbarState(true);
        if (this.$xDataControl) {
            this.$emit('ctrl-event', { controlname: this.xDataControlName, action: "load", data: args });
        }
    }

    /**
     * 部件事件
     * @param ctrl 部件 
     * @param action  行为
     * @param data 数据
     * 
     * @memberof ExpBarControlBase
     */
    public onCtrlEvent(controlname: any, action: any, data: any) {
        if (controlname && Object.is(controlname, this.xDataControlName)) {
            switch (action) {
                case "selectionchange":
                    this.onSelectionChange(data);
                    return;
                case "load":
                    this.onLoad(data, action);
                    return;
                case 'beforeload':
                    Object.assign(data, { query: this.searchText });
                    break;
            }
        }
        super.onCtrlEvent(controlname, action, data);
    }

    /**
     * 搜索
     *
     * @param {*} event
     * @memberof ExpBarControlBase
     */
    public onSearch(event: any) {
        if (this.xDataControlName) {
            this.viewState.next({ tag: this.xDataControlName, action: 'load', data: { query: event } });
        }
    }

    /**
     * 渲染头部
     *
     * @return {*} 
     * @memberof ExpBarControlBase
     */
    public renderHeader() {
        const quickGroupSearch = this.$parent.$slots?.['quickGroupSearch'];
        if (!quickGroupSearch && !this.controlInstance.showTitleBar && !this.controlInstance.enableSearch && !(this.toolbarModels && this.toolbarModels.length)) {
            return null;
        }
        const image = this.controlInstance.M.getPSSysImage;
        return (
            <div class="control-header">
                {this.controlInstance.showTitleBar ? <div class="control-header__left">
                    <div class="control-header__left__caption">
                        {image?.imagePath && <img src={image.imagePath} />}
                        {image?.cssClass && <i class={image.cssClass}></i>}
                        <span class="text">{this.$tl(this.controlInstance.getTitlePSLanguageRes()?.lanResTag, this.controlInstance.title)}</span>
                    </div>
                </div> : null}
                <div class="control-header__right">
                    {quickGroupSearch ? <div class="control-header__right__quickgroupsearch"> {quickGroupSearch}</div> : null}
                    {this.controlInstance.enableSearch ?
                        <div class="control-header__right__quicksearch">
                            <app-quick-search v-model={this.searchText} on-search={(event: any) => this.onSearch(event)} appDataEntity={this.controlInstance.getPSAppDataEntity?.()} />
                        </div> : null}
                    <div class="control-header__right__toolbar">
                        {this.renderToolbar()}
                    </div>
                </div>
            </div>
        )
    }

    /**
     * 绘制导航栏主体内容
     * 
     * @memberof ExpBarControlBase
     */
    public renderMainContent() {
        if (!this.controlIsLoaded) {
            return null;
        }
        const { controlClassNames } = this.renderOptions;
        return (
            <div
                ref={`${this.appDeCodeName}-${this.controlInstance.codeName?.toLowerCase()}`}
                class={[controlClassNames]}>
                {this.renderHeader()}
                <div class='control-content'>
                    {this.renderXDataControl()}
                </div>
            </div>
        )
    }

    /**
     * @description 部件销毁
     * @memberof ExpBarControlBase
     */
    public ctrlDestroyed() {
        super.ctrlDestroyed();
        if (this.expbarControlEvent) {
            this.expbarControlEvent.unsubscribe();
        }
    }

}