import { IPSAppDataEntity, IPSAppDEField, IPSAppDEMultiDataView, IPSControlNavigatable, IPSDECalendar, IPSDETBUIActionItem, IPSDEToolbar, IPSDEToolbarItem, IPSDETree, IPSDEUIAction, IPSExpBar, IPSSysImage, IPSLanguageRes, IPSSysMap, IPSDEChart } from '@ibiz/dynamic-model-api';
import { throttle, ExpBarControlInterface, ModelTool, Util, ViewTool } from 'ibiz-core';
import { Subscription } from 'rxjs';
import { 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 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 {*} [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 });
                }
            });
        }
    }

    /**
     * 设置导航区工具栏禁用状态
     *
     * @param {boolean} state
     * @return {*} 
     * @memberof ExpBarControlBase
     */
    public calcToolbarItemState(state: boolean) {
        let _this: any = this;
        const computeItemState = (models: any[]) => {
            if (models && models.length) {
                for (const key in models) {
                    if (!models.hasOwnProperty(key)) {
                        return;
                    }
                    const _item = models[key];
                    if (_item.uiaction && (Object.is(_item.uiaction.actionTarget, 'SINGLEKEY') || Object.is(_item.uiaction.actionTarget, 'MULTIKEY'))) {
                        models[key].disabled = state;
                    }
                    models[key].visabled = true;
                    if (_item.noprivdisplaymode && _item.noprivdisplaymode === 6) {
                        models[key].visabled = false;
                    }
                    if (models[key].itemType === 'ITEMS' && models[key].items) {
                        computeItemState(models[key].items);
                    }
                }
            }
        }
        computeItemState(_this.toolbarModels);
        this.calcNavigationToolbarState();
    }

    /**
     * 初始化工具栏数据
     * 
     * @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).data,
                        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;
        }
    }

    /**
     * 绘制数据部件
     *
     * @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;
        }
        AppViewLogicService.getInstance().executeViewLogic(`${this.controlInstance.name?.toLowerCase()}_toolbar_${data.tag}_click`, $event, this, undefined, this.controlInstance.getPSAppViewLogics() || []);
    }

    /**
     * 计算导航工具栏权限状态
     * 
     * @memberof ExpBarControlBase
     */
    public calcNavigationToolbarState() {
        let _this: any = this;
        if (_this.toolbarModels) {
            ViewTool.calcActionItemAuthState({}, this.toolbarModels, this.appUIService);
        }
    }

    /**
     * 刷新
     *
     * @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 {*}  {void}
     * @memberof ExpBarControlBase
     */
    public onSelectionChange(args: any[]): void {
        let tempContext: any = {};
        let tempViewParam: any = {};
        if (args.length === 0) {
            this.calcToolbarItemState(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);
            }
            Object.assign(tempContext, { viewpath: this.navViewName });
            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.calcToolbarItemState(arg && key && arg[key] ? false : true);
                    this.$emit("ctrl-event", { controlname: this.controlInstance.name, action: "selectionchange", data: params });
                }
            })
        } else {
            this.calcToolbarItemState(true);
            return;
        }
    }

    /**
     * load完成事件
     * 
     * @param {*} args 加载数据
     * @param {string} [tag]
     * @param {*} [$event2]
     * @memberof ExpBarControlBase
     */
    public onLoad(args: any, tag?: string, $event2?: any) {
        this.calcToolbarItemState(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;
        }
        return (
            <div class="expbarcontrol-header">
                {this.controlInstance.showTitleBar ?
                    <div class="caption">
                        <icon type="ios-home-outline" />
                        <span class="text">{this.$tl(this.controlInstance.getTitlePSLanguageRes()?.lanResTag, this.controlInstance.title)}</span>
                    </div> : null}
                {quickGroupSearch ? quickGroupSearch : null}
                {this.controlInstance.enableSearch ?
                    <app-quick-search v-model={this.searchText} on-search={(event: any) => this.onSearch(event)} appDataEntity={this.controlInstance.getPSAppDataEntity?.()} /> : null}
                {this.renderToolbar()}
            </div>
        )
    }

    /**
     * 绘制导航栏主体内容
     * 
     * @memberof ExpBarControlBase
     */
    public renderMainContent() {
        if (!this.controlIsLoaded) {
            return null;
        }
        return (
            <div
                ref={`${this.appDeCodeName}-${this.controlInstance.codeName?.toLowerCase()}`}
                class={['expbarcontrol', `app-${this.$xDataControl.controlType?.toLowerCase()}-exp-bar`, this.renderOptions?.controlClassNames]}>
                {this.renderHeader()}
                <div class="expbarcontrol-xdata-ctrl">
                    {this.renderXDataControl()}
                </div>
            </div>
        )
    }

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

}
