import { UIActionContext } from "@/logic/ui-logic";
import { LogicReturnType } from "@/logic/const/logic-return-type";
import { UILogicParamType } from "@/logic/const/ui-logic-param-type";
import { Util, Verify } from "@/utils";
import { AppMessageBox } from "@/utils/app-message-box/app-message-box";
import { Subject } from "rxjs";
import { Environment } from "@/environments/environment";
import InitDataLogic from '@/service/ibizbook/init-data-logic';
/**
 * 表格加载
 *
 * @export
 * @class GridLoadUILogicBase
 */
export default class GridLoadUILogicBase {

    /**
     * Creates an instance of  GridLoadBase.
     * 
     * @param {*} [opts={}]
     * @memberof GridLoadUILogicBase
     */
    constructor(opts: any = {}) { }

    /**
     * 逻辑参数
     *
     * @protected
     * @type {any[]}
     * @memberof GridLoadUILogicBase
     */
    protected logicParams: any[] = [
        {
            name: '当前表格',
            codeName: 'grid',
            ctrlParam: true,
        },
        {
            name: '额外参数',
            codeName: 'otherParam',
            entityParam: true,
        },
        {
            name: '当前搜索表单',
            codeName: 'searchForm',
            ctrlParam: true,
        },
        {
            name: '当前视图参数',
            codeName: 'viewParam',
            viewNavDataParam: true,
        },
        {
            name: '当前视图',
            codeName: 'view',
            activeViewParam: true,
        },
        {
            name: '路由会话变量',
            codeName: 'routerParam',
            routeViewSessionParam: true,
        },
        {
            name: '当前系统名称',
            codeName: 'systemName',
        },
        {
            name: '传入变量',
            codeName: 'Default',
            default: true,
            entityParam: true,
        },
        {
            name: '应用上下文',
            codeName: 'context',
            navContextParam: true,
        },
    ];

    /**
     * 执行前
     *
     * @param {*} args
     * @param {*} [context={}]
     * @param {*} [params={}]
     * @param {*} [$event]
     * @param {*} [xData]
     * @param {*} [actioncontext]
     * @param {string} [srfParentDeName]
     * @return {*} 
     * @memberof GridLoadUILogicBase
     */
    public beforeExecute(args: any, context: any = {}, params: any = {},
        $event?: any, xData?: any, actioncontext?: any, srfParentDeName?: string) {
        return new UIActionContext(this.logicParams, args, context, params, $event, xData, actioncontext, srfParentDeName)
    }

    /**
     * 执行
     *
     * @param {any[]} args
     * @param {*} [context={}]
     * @param {*} [params={}]
     * @param {*} [$event]
     * @param {*} [xData]
     * @param {*} [actionContext]
     * @param {string} [srfParentDeName]
     * @memberof GridLoadUILogicBase
     */
    async execute(args: any[], context:any = {} ,params: any = {}, $event?: any, xData?: any, actioncontext?: any, srfParentDeName?: string) {
        try {
            const actionContext = this.beforeExecute(args, context, params, $event, xData, actioncontext, srfParentDeName);
            await this.execute_begin_node(actionContext);
            return actionContext.getResult();
        } catch (error: any) {
            throw new Error(`${error && error.message ? error.message : '发生未知错误！'}`);
        }
    }

    /**
     * 获取条件参数
     *
     * @param {UIActionContext} actionContext 界面逻辑上下文
     * @param {string} param 节点参数
     * @param {string} property 参数属性
     * @return {*} 
     * @memberof GridLoadUILogicBase
     */
    public getCondParam(actionContext: UIActionContext, param: string, property: string) {
        const resultParam = actionContext.getParam(param).getReal();
        //  当不存在参数属性时，返回直接值
        if (property === '') {
            return resultParam;
        }
        if (resultParam && resultParam.hasOwnProperty(property)) {
            return resultParam[property];
        }
        return null;
    }

    /**
     * 开始
     *
     * @param {UIActionContext} actionContext 界面逻辑上下文
     * @memberof GridLoadUILogicBase
     */
    protected async execute_begin_node(actionContext: UIActionContext) {
        actionContext.setResult(actionContext.defaultParam.getReal());
        console.log('已完成执行 开始 节点');
        await this.execute_bindparam1_node(actionContext);
    }
    
    /**
     * 消息弹窗
     *
     * @param {UIActionContext} actionContext 界面逻辑上下文
     * @memberof GridLoadUILogicBase
     */
    protected async execute_msgbox1_node(actionContext: UIActionContext) {
        return new Promise<void>((resolve: any) => {
            const msgBoxParam: any = actionContext.getParam('');
            const data = msgBoxParam ? msgBoxParam.getReal() : {};
            const options = {
                type: 'INFO',
                title: data && data.title ? data.title : '触发',
                content: data && data.message ? data.message : '我被触发啦',
                buttonType: 'ok',
                showMode: 'center',
                showClose: false,
                mask: true,
                maskClosable: true
            };
            const subject: Subject<any> | null =  AppMessageBox.getInstance().open(options);
            if (subject) {
                const handleResponse = (result: any) => {
                    if (msgBoxParam) {
                        msgBoxParam.bind(result);
                    }
                    actionContext.bindLastReturnParam(result);
                    resolve(this.execute_debugparam1_node(actionContext));
                    console.log('已完成执行 消息弹窗 节点');
                }
                const subscription = subject.subscribe((result: any) => {
                    resolve(handleResponse(result));
                    subscription!.unsubscribe();
                    subject.complete();
                });
            } else {
                resolve(true);
                console.log('已完成执行 消息弹窗 节点');
            }
        });
    }
    
    /**
     * 实体行为
     *
     * @param {UIActionContext} actionContext 界面逻辑上下文
     * @memberof GridLoadUILogicBase
     */
    protected async execute_deaction1_node(actionContext: UIActionContext) {
        const dstParam = actionContext.getParam('otherParam');
        if (!Object.is(dstParam.logicParamType, UILogicParamType.entityListParam) && !Object.is(dstParam.logicParamType, UILogicParamType.entityParam)) {
            throw new Error(`实体行为操作参数只能为数据对象变量类型或者数据对象列表类型`);
        }
        const retParam = actionContext.getParam('Default');
        if (dstParam) {
            try {
                const service: any = await window.entityServiceRegister.getService('ibizbook');
                const getTempContext = (data: any) => {
                    const tempContext = Util.deepCopy(actionContext.context);
                    if (data) {
                        Object.assign(tempContext, data);
                    }
                    return tempContext;
                }
                // 数据对象变量类型
                if (Object.is(dstParam.logicParamType, UILogicParamType.entityParam)) {
                    const tempContext = getTempContext(dstParam.getReal());
                    const res = await service['Get'](tempContext, dstParam.getReal() ? dstParam.getReal() : {});
                    if (res && res.status === 200 && res.data) {
                        if (retParam) {
                            retParam.bind(res.data);
                        }
                        actionContext.bindLastReturnParam(res.data);
                    } else {
                        throw new Error(`执行实体行为失败`);
                    }
                } else {
                    // 数据对象列表类型
                    if (dstParam.getReal() && (dstParam.getReal().length > 0)) {
                        if (dstParam.getReal().length > 20) {
                            throw new Error(`操作数据量超过20条，建议使用后台处理逻辑`);
                        }
                        let promises: any[] = [];
                        dstParam.getReal().forEach((item: any) => {
                            const tempContext = getTempContext(item);
                            promises.push(service['Get'](tempContext, item ? item : {}));
                        })
                        const resArray = await Promise.all(promises);
                        if (resArray && resArray.length > 0) {
                            const resultArray: any[] = [];
                            resArray.forEach((res: any) => {
                                if (res && res.status === 200 && res.data) {
                                    resultArray.push(res.data);
                                }
                            })
                            if (retParam) {
                                retParam.bind(resultArray);
                            }
                            actionContext.bindLastReturnParam(resultArray);
                        } else {
                            throw new Error(`执行实体行为失败`);
                        }
                    } else {
                        if (retParam) {
                            retParam.bind([]);
                        }
                        actionContext.bindLastReturnParam([]);
                    }
                }
            } catch (error: any) {
                throw new Error(`${error.message ? error.message : error.data && error.data.message ? error.data.message : '执行实体行为失败'}`);
            }
        } else {
            throw new Error(`操作参数缺失！`);
        }
        console.log('已完成执行 实体行为 节点');
        await this.execute_end1_node(actionContext);
    }
    
    /**
     * 视图部件事件触发
     *
     * @param {UIActionContext} actionContext 界面逻辑上下文
     * @memberof GridLoadUILogicBase
     */
    protected async execute_viewctrlfireevent1_node(actionContext: UIActionContext) {
        //  事件名称
        const eventName: string = 'load';
        //  事件参数
        const eventParam = 'viewParam';
        //  触发对象
        const fireCtrl = 'grid';
        if (!eventParam || !eventParam || !fireCtrl) {
            throw new Error(`触发对象、事件名称或者事件参数缺失`);
        }
        // 触发UI对象
        const fireUICtrl = actionContext.getParam(fireCtrl).getReal();
        // 事件参数
        const eventArgs = actionContext.getParam(eventParam).getReal();
        if (!fireUICtrl) {
            throw new Error(`获取触发对象异常`);
        }
        try {
            // 自身触发
            fireUICtrl.$emit(eventName, eventArgs);
            actionContext.bindLastReturnParam(null);
        } catch (error:any) {
            throw new Error(`视图部件事件触发未执行成功！`);
        }
        console.log('已完成执行 视图部件事件触发 节点');
    }
    
    /**
     * 调试逻辑参数
     *
     * @param {UIActionContext} actionContext 界面逻辑上下文
     * @memberof GridLoadUILogicBase
     */
    protected async execute_debugparam1_node(actionContext: UIActionContext) {
        const dstParamValue = actionContext.getParam('context').getReal();
        actionContext.bindLastReturnParam(null);
        console.log('逻辑节点 调试逻辑参数 操作参数值: ', dstParamValue);
        console.log('已完成执行 调试逻辑参数 节点');
        await this.execute_viewctrlfireevent1_node(actionContext);
    }
    
    /**
     * 绑定搜索表单
     *
     * @param {UIActionContext} actionContext 界面逻辑上下文
     * @memberof GridLoadUILogicBase
     */
    protected async execute_bindparam1_node(actionContext: UIActionContext) {
        try {
            //  源数据
            const srcParam = actionContext.getParam('view');
            //  目标数据
            const dstParam = actionContext.getParam('searchForm');
            //  源属性
            const srcFieldName: string = 'searchform';
            if (srcFieldName) {
                dstParam.bind(srcParam.get(srcFieldName));
            } else {
                dstParam.bind(srcParam.getReal());
            }
            actionContext.bindLastReturnParam(null);
        } catch (error: any) {
            throw new Error(`逻辑参数当前搜索表单 ${error && error.message ? error.message : '发生未知错误!'}`);
        }
        console.log('已完成执行 绑定搜索表单 节点');
        await this.execute_bindparam2_node(actionContext);
    }
    
    /**
     * 准备参数
     *
     * @param {UIActionContext} actionContext 界面逻辑上下文
     * @memberof GridLoadUILogicBase
     */
    protected async execute_preparejsparam2_node(actionContext: UIActionContext) {
        try {
            //  目标数据
            const dstParam_1: any = actionContext.getParam('context');
            //  无值类型
            //  直接值
            const result_1 = '12';
            dstParam_1.set('ibizbook', result_1);
        } catch (error: any) {
            throw new Error(`逻辑节点 准备参数 ${error && error.message ? error.message : '发生未知错误！'}`);
        }
        console.log('已完成执行 准备参数 节点');
        await this.execute_delogic1_node(actionContext);
    }
    
    /**
     * 实体处理逻辑
     *
     * @param {UIActionContext} actionContext 界面逻辑上下文
     * @memberof GridLoadUILogicBase
     */
    protected async execute_delogic1_node(actionContext: UIActionContext) {
        const dstParam = actionContext.getParam('viewParam');
        const retParam = actionContext.getParam('viewParam');
        if (dstParam) {
            try {
                const deLogic: InitDataLogic = new InitDataLogic({ context: actionContext.context, data: dstParam.getReal() ? dstParam.getReal() : {} });
                const result = await deLogic.onExecute(actionContext.context, dstParam.getReal() ? dstParam.getReal() : {}, false);
                if (result) {
                    if(retParam){
                        retParam.bind(result);
                    }
                    actionContext.bindLastReturnParam(result);
                } else {
                    throw new Error(`调用实体处理逻辑异常`);
                }
            } catch (error: any) {
                throw new Error(`调用实体处理逻辑异常${error && error.message ? error.message : ''}`);
            }
        } else {
            throw new Error(`操作参数缺失！`);
        }
        console.log('已完成执行 实体处理逻辑 节点');
        await this.execute_msgbox1_node(actionContext);
        await this.execute_preparejsparam1_node(actionContext);
    }
    
    /**
     * 绑定表格
     *
     * @param {UIActionContext} actionContext 界面逻辑上下文
     * @memberof GridLoadUILogicBase
     */
    protected async execute_bindparam2_node(actionContext: UIActionContext) {
        try {
            //  源数据
            const srcParam = actionContext.getParam('view');
            //  目标数据
            const dstParam = actionContext.getParam('grid');
            //  源属性
            const srcFieldName: string = 'grid';
            if (srcFieldName) {
                dstParam.bind(srcParam.get(srcFieldName));
            } else {
                dstParam.bind(srcParam.getReal());
            }
            actionContext.bindLastReturnParam(null);
        } catch (error: any) {
            throw new Error(`逻辑参数当前表格 ${error && error.message ? error.message : '发生未知错误!'}`);
        }
        console.log('已完成执行 绑定表格 节点');
        await this.execute_viewctrlinvoke1_node(actionContext);
    }
    
    /**
     * 表格加载
     *
     * @param {UIActionContext} actionContext 界面逻辑上下文
     * @memberof GridLoadUILogicBase
     */
    protected async execute_viewctrlinvoke2_node(actionContext: UIActionContext) {
        const invokeCtrl = 'grid';
        const invokeMethod = 'load';
        const invokeParam = 'viewParam';
        if (!invokeCtrl || !invokeMethod) {
            throw new Error(`界面对象或者调用方法缺失`);
        }
        const invokeUICtrl = actionContext.getParam(invokeCtrl).getReal();
        if (invokeUICtrl[invokeMethod] && invokeUICtrl[invokeMethod] instanceof Function) {
            try {
                const result = await invokeUICtrl[invokeMethod]();
                if (invokeParam) {
                    actionContext.getParam(invokeParam).bind(result);
                }
                actionContext.bindLastReturnParam(result);
            } catch (error:any) {
                throw new Error(`${invokeCtrl}界面对象调用${invokeMethod}方法发生异常`);
            }
        } else {
            throw new Error(`${invokeCtrl}界面对象不存在${invokeMethod}方法`);
        }
        console.log('已完成执行 表格加载 节点');
        await this.execute_preparejsparam2_node(actionContext);
    }
    
    /**
     * 结束
     *
     * @param {UIActionContext} actionContext 界面逻辑上下文
     * @memberof GridLoadUILogicBase
     */
    protected async execute_end1_node(actionContext: UIActionContext) {
        const strReturnType: string = 'LOGICPARAM';
        if (Object.is(strReturnType, LogicReturnType.NONEVALUE) || Object.is(strReturnType, LogicReturnType.NULLVALUE)) {
            actionContext.setResult(null);
        } else if (Object.is(strReturnType, LogicReturnType.SRCVALUE)) {
            actionContext.setResult('');
        } else if (Object.is(strReturnType, LogicReturnType.BREAK)) {
            actionContext.setResult(LogicReturnType.BREAK);
        } else if (Object.is(strReturnType, LogicReturnType.LOGICPARAM) || Object.is(strReturnType, LogicReturnType.LOGICPARAMFIELD)) {
            const returnParam = actionContext.getParam('Default');
            if (Object.is(strReturnType, LogicReturnType.LOGICPARAM)) {
                actionContext.setResult(returnParam.getReal());
            } else {
                actionContext.setResult(returnParam.get(''));
            }
        } else {
            throw new Error(`无法识别的返回值类型${strReturnType}`);
        }
        console.log('已完成执行 结束 节点');
    }
    
    /**
     * 搜索表单loadDraft
     *
     * @param {UIActionContext} actionContext 界面逻辑上下文
     * @memberof GridLoadUILogicBase
     */
    protected async execute_viewctrlinvoke1_node(actionContext: UIActionContext) {
        const invokeCtrl = 'searchForm';
        const invokeMethod = 'loadDraft';
        const invokeParam = 'viewParam';
        if (!invokeCtrl || !invokeMethod) {
            throw new Error(`界面对象或者调用方法缺失`);
        }
        const invokeUICtrl = actionContext.getParam(invokeCtrl).getReal();
        if (invokeUICtrl[invokeMethod] && invokeUICtrl[invokeMethod] instanceof Function) {
            try {
                const result = await invokeUICtrl[invokeMethod]();
                if (invokeParam) {
                    actionContext.getParam(invokeParam).bind(result);
                }
                actionContext.bindLastReturnParam(result);
            } catch (error:any) {
                throw new Error(`${invokeCtrl}界面对象调用${invokeMethod}方法发生异常`);
            }
        } else {
            throw new Error(`${invokeCtrl}界面对象不存在${invokeMethod}方法`);
        }
        console.log('已完成执行 搜索表单loadDraft 节点');
        await this.execute_viewctrlinvoke2_node(actionContext);
    }
    
    /**
     * 准备参数
     *
     * @param {UIActionContext} actionContext 界面逻辑上下文
     * @memberof GridLoadUILogicBase
     */
    protected async execute_preparejsparam1_node(actionContext: UIActionContext) {
        try {
            //  目标数据
            const dstParam_1: any = actionContext.getParam('otherParam');
            //  无值类型
            //  直接值
            const result_1 = '12';
            dstParam_1.set('book', result_1);
        } catch (error: any) {
            throw new Error(`逻辑节点 准备参数 ${error && error.message ? error.message : '发生未知错误！'}`);
        }
        console.log('已完成执行 准备参数 节点');
        await this.execute_deaction1_node(actionContext);
    }
    

}