<#-- START: 计算下一节点  -->
<#macro computeNextNode logicNode>
    <#if logicNode.getPSDEUILogicLinks?? && logicNode.getPSDEUILogicLinks()??>
        <#list logicNode.getPSDEUILogicLinks() as link>
            <#if link.getDstPSDEUILogicNode?? && link.getDstPSDEUILogicNode()??>
                <#if link.getPSDEUILogicLinkGroupCond?? && link.getPSDEUILogicLinkGroupCond()??>
        //  暂未支持连接条件
                </#if>
        await this.execute_${link.getDstPSDEUILogicNode().codeName?lower_case}_node(actionContext);
            </#if>
        </#list>
    </#if>
</#macro>
<#-- END: 计算下一节点  -->

<#--  START: 开始节点  -->
<#macro beginNode logicNode>
        actionContext.setResult(actionContext.defaultParam.getReal());
        console.log('已完成执行 ${logicNode.name} 节点');
</#macro>
<#--  END: 开始节点  -->

<#--  START: 准备处理参数节点  -->
<#macro prepareParamNode logicNode>
        //  TODO 等待补充
        console.log('已完成执行 ${logicNode.name} 节点');
</#macro>
<#--  END: 准备处理参数节点  -->

<#--  START: 重置参数节点  -->
<#macro resetParamNode logicNode>
        //  TODO 等待补充
        console.log('已完成执行 ${logicNode.name} 节点');
</#macro>
<#--  END: 重置参数节点  -->

<#--  START: 拷贝参数节点  -->
<#macro copyParamNode logicNode>
    <#if logicNode.getDstPSDEUILogicParam?? && logicNode.getDstPSDEUILogicParam()?? && logicNode.getSrcPSDEUILogicParam?? && logicNode.getSrcPSDEUILogicParam()??>
        try {
            // 源数据
            const srcParam:any = actionContext.getParam('${logicNode.getSrcPSDEUILogicParam().codeName}');
            // 目标数据
            const dstParam: any = actionContext.getParam('${logicNode.getDstPSDEUILogicParam().codeName}');
            srcParam.copyTo(dstParam);
            actionContext.bindLastReturnParam(null);
        } catch (error: any) {
            throw new Error(`逻辑参数 ${logicNode.getDstPSDEUILogicParam().name} <#noparse>${error ## error.message ? error.message : '发生未知错误！'}`</#noparse>);
        }
    <#else>
        throw new Error('操作参数或者源参数缺失!');
    </#if>
        console.log('已完成执行 ${logicNode.name} 节点');
</#macro>
<#--  END: 拷贝参数节点  -->

<#--  START: 绑定参数节点  -->
<#macro bindParamNode logicNode>
    <#if logicNode.getDstPSDEUILogicParam?? && logicNode.getDstPSDEUILogicParam()?? && logicNode.getSrcPSDEUILogicParam?? && logicNode.getSrcPSDEUILogicParam()??>
        try {
            //  源数据
            const srcParam = actionContext.getParam('${logicNode.getSrcPSDEUILogicParam().codeName}');
            //  目标数据
            const dstParam = actionContext.getParam('${logicNode.getDstPSDEUILogicParam().codeName}');
            //  源属性
            const srcFieldName: string = '<#if logicNode.getSrcFieldName?? && logicNode.getSrcFieldName()??>${logicNode.getSrcFieldName()?lower_case}</#if>';
            if (srcFieldName) {
                dstParam.bind(srcParam.get(srcFieldName));
            } else {
                dstParam.bind(srcParam.getReal());
            }
            actionContext.bindLastReturnParam(null);
        } catch (error: any) {
            throw new Error(`逻辑参数<#if logicNode.getDstPSDEUILogicParam?? && logicNode.getDstPSDEUILogicParam()??>${logicNode.getDstPSDEUILogicParam().name}</#if> <#noparse>${error && error.message ? error.message : '发生未知错误!'}</#noparse>`);
        }
    <#else>
        throw new Error('操作参数或者源参数缺失!');
    </#if>
        console.log('已完成执行 ${logicNode.name} 节点');
</#macro>
<#--  END: 绑定参数节点 -->

<#--  START: 重新建立参数节点  -->
<#macro renewParamNode logicNode>
        //  TODO 等待补充
        console.log('已完成执行 ${logicNode.name} 节点');
</#macro>
<#--  END: 重新建立参数节点  -->

<#--  START: 调用实体界面行为节点  -->
<#macro deUIActionNode logicNode>
        //  TODO 等待补充
        console.log('已完成执行 ${logicNode.name} 节点');
</#macro>
<#--  END: 调用实体界面行为节点  -->

<#--  START: 行为处理节点  -->
<#macro deActionNode logicNode>
        const dstParam = actionContext.getParam('<#if logicNode.getDstPSDEUILogicParam?? && logicNode.getDstPSDEUILogicParam()??>${logicNode.getDstPSDEUILogicParam().codeName}</#if>');
        if (!Object.is(dstParam.logicParamType, UILogicParamType.entityListParam) && !Object.is(dstParam.logicParamType, UILogicParamType.entityParam)) {
            throw new Error(`实体行为操作参数只能为数据对象变量类型或者数据对象列表类型`);
        }
        const retParam = actionContext.getParam('<#if logicNode.getRetPSDEUILogicParam?? && logicNode.getRetPSDEUILogicParam()??>${logicNode.getRetPSDEUILogicParam().codeName}</#if>');
        console.log('已完成执行 ${logicNode.name} 节点');
</#macro>
<#--  END: 行为处理节点  -->

<#--  START: 实体处理逻辑节点  -->
<#macro deLogicNode logicNode>
        //  TODO 等待补充
        console.log('已完成执行 ${logicNode.name} 节点');
</#macro>
<#--  END: 实体处理逻辑节点  -->

<#--  START: 实体数据集节点  -->
<#macro deDataSetNode logicNode>
        //  TODO 等待补充
        console.log('已完成执行 ${logicNode.name} 节点');
</#macro>
<#--  END: 实体数据集节点  -->

<#--  START: 附加到数组参数节点  -->
<#macro appendParamNode logicNode>
        //  TODO 等待补充
        console.log('已完成执行 ${logicNode.name} 节点');
</#macro>
<#--  END: 附加到数组参数节点  -->

<#--  START: 排序数组参数节点  -->
<#macro sortParamNode logicNode>
        //  TODO 等待补充
        console.log('已完成执行 ${logicNode.name} 节点');
</#macro>
<#--  END: 排序数组参数节点  -->

<#--  START: 视图部件调用节点  -->
<#macro viewCtrlInvokeNode logicNode>
        const invokeCtrl = '<#if logicNode.getInvokeCtrl?? && logicNode.getInvokeCtrl()??>${logicNode.getInvokeCtrl().codeName}</#if>';
        const invokeMethod = '<#if logicNode.getInvokeMethod?? && logicNode.getInvokeMethod()??>${logicNode.getInvokeMethod()}</#if>';
        const invokeParam = '<#if logicNode.getInvokeParam?? && logicNode.getInvokeParam()??>${logicNode.getInvokeParam().codeName}</#if>';
        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) {
                <#noparse>throw new Error(`${invokeCtrl}界面对象调用${invokeMethod}方法发生异常`);</#noparse>
            }
        } else {
            <#noparse>throw new Error(`${invokeCtrl}界面对象不存在${invokeMethod}方法`);</#noparse>
        }
        console.log('已完成执行 ${logicNode.name} 节点');
</#macro>
<#--  END: 视图部件调用节点  -->

<#--  START: 视图部件事件触发节点  -->
<#macro viewCtrlFireEventNode logicNode>
        //  TODO 等待补充
        console.log('已完成执行 ${logicNode.name} 节点');
</#macro>
<#--  END: 视图部件事件触发节点  -->

<#--  START: 调试逻辑参数节点  -->
<#macro debugParamNode logicNode>
        //  TODO 等待补充
        console.log('已完成执行 ${logicNode.name} 节点');
</#macro>
<#--  END: 调试逻辑参数节点  -->

<#--  START: 消息弹窗节点  -->
<#macro msgBoxNode logicNode>
        //  TODO 等待补充
        console.log('已完成执行 ${logicNode.name} 节点');
</#macro>
<#--  END: 消息弹窗节点  -->

<#--  START: 前端代码节点  -->
<#macro rawJSCoreNode logicNode>
        //  TODO 等待补充
        console.log('已完成执行 ${logicNode.name} 节点');
</#macro>
<#--  END: 前端代码节点  -->

<#--  START: 异常处理节点  -->
<#macro throwExceptionNode logicNode>
        //  TODO 等待补充
        console.log('已完成执行 ${logicNode.name} 节点');
</#macro>
<#--  END: 异常处理节点  -->

<#--  START: 结束节点  -->
<#macro endNode logicNode>
        const strReturnType: string = '<#if logicNode.getReturnType?? && logicNode.getReturnType()??>${logicNode.getReturnType()}</#if>';
        if (Object.is(strReturnType, LogicReturnType.NONEVALUE) || Object.is(strReturnType, LogicReturnType.NULLVALUE)) {
            actionContext.setResult(null);
        } else if (Object.is(strReturnType, LogicReturnType.SRCVALUE)) {
            actionContext.setResult('<#if logicNode.getRawValue?? && logicNode.getRawValue()??>${logicNode.getRawValue()}</#if>');
        } 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('<#if logicNode.getReturnParam?? && logicNode.getReturnParam()??>${logicNode.getReturnParam().codeName}</#if>');
            if (Object.is(strReturnType, LogicReturnType.LOGICPARAM)) {
                actionContext.setResult(returnParam.getReal());
            } else {
                actionContext.setResult(returnParam.get('<#if logicNode.getDstFieldName?? && logicNode.getDstFieldName()??>${logicNode.getDstFieldName()}</#if>'));
            }
        } else {
            <#noparse>throw new Error(`无法识别的返回值类型${strReturnType}`);</#noparse>
        }
        console.log('已完成执行 ${logicNode.name} 节点');
</#macro>
<#--  END: 结束节点  -->


<#--  执行节点  -->
<#macro executenode logicNode>
    /**
     * ${logicNode.name}
     *
     * @param {UIActionContext} actionContext 界面逻辑上下文
     */
    protected async execute_${logicNode.codeName?lower_case}_node(actionContext: UIActionContext) {
        //  <#if item?? && item.name??>${item.name}</#if>
        <#if logicNode.getLogicNodeType() == 'BEGIN'>
        <#--  开始节点  -->
            <@beginNode logicNode/>
        <#elseif logicNode.getLogicNodeType() == 'PREPAREJSPARAM'>
        <#--  准备参数节点  -->
            <@prepareParamNode logicNode/>
        <#elseif logicNode.getLogicNodeType() == 'RESETPARAM'>
        <#--  重置参数节点  -->
            <@resetParamNode logicNode/>
        <#elseif logicNode.getLogicNodeType() == 'COPYPARAM'>
        <#--  拷贝参数节点  -->
            <@copyParamNode logicNode/>
        <#elseif logicNode.getLogicNodeType() == 'BINDPARAM'>
        <#--  绑定参数节点  -->
            <@bindParamNode logicNode/>
        <#elseif logicNode.getLogicNodeType() == 'RENEWPARAM'>
        <#--  重新建立参数节点  -->
            <@renewParamNode logicNode/>
        <#elseif logicNode.getLogicNodeType() == 'DEUIACTION'>
        <#--  调用实体界面行为节点  -->
            <@deUIActionNode logicNode/>
        <#elseif logicNode.getLogicNodeType() == 'DEACTION'>
        <#--  行为处理节点  -->
            <@deActionNode logicNode/>
        <#elseif logicNode.getLogicNodeType() == 'DELOGIC'>
        <#--  实体处理逻辑节点  -->
            <@deLogicNode logicNode/>
        <#elseif logicNode.getLogicNodeType() == 'DEDATASET'>
        <#--  实体数据集节点  -->
            <@deDataSetNode logicNode/>
        <#elseif logicNode.getLogicNodeType() == 'APPENDPARAM'>
        <#--  附加到数组参数节点  -->
            <@appendParamNode logicNode/>
        <#elseif logicNode.getLogicNodeType() == 'SORTPARAM'>
        <#--  排序数组参数节点  -->
            <@sortParamNode logicNode/>
        <#elseif logicNode.getLogicNodeType() == 'VIEWCTRLINVOKE'>
        <#--  视图部件调用节点  -->
            <@viewCtrlInvokeNode logicNode/>
        <#elseif logicNode.getLogicNodeType() == 'VIEWCTRLFIREEVENT'>
        <#--  视图部件事件触发节点  -->
            <@viewCtrlFireEventNode logicNode/>
        <#elseif logicNode.getLogicNodeType() == 'DEBUGPARAM'>
        <#--  调试逻辑参数节点  -->
            <@debugParamNode logicNode/>
        <#elseif logicNode.getLogicNodeType() == 'MSGBOX'>
        <#--  消息弹窗节点  -->
            <@msgBoxNode logicNode/>
        <#elseif logicNode.getLogicNodeType() == 'RAWJSCODE'>
        <#--  前端代码节点  -->
            <@rawJSCoreNode logicNode/>
        <#elseif logicNode.getLogicNodeType() == 'THROWEXCEPTION'>
        <#--  异常处理节点  -->
            <@throwExceptionNode logicNode/>
        <#elseif logicNode.getLogicNodeType() == 'END'>
        <#--  结束节点  -->
            <@endNode logicNode/>
        <#else>
            console.log('${logicNode.getLogicNodeType()}暂未支持');
        </#if>
            <@computeNextNode logicNode/>
    }
</#macro>