"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const parser = require("@babel/parser");
const t = require("@babel/types");
const traverse_1 = require("@babel/traverse");
const utils_1 = require("../utils/utils");
const { generator } = require('mvvm-template-parser');
const formMethods = [
    'getFieldsValue',
    'setFieldsValue',
    'setFieldSource',
    'setFieldDisabled',
    'setFieldVisible',
    'setFieldRequired',
    'resetFields',
];
const modalMethods = ['show', 'hide'];
const logicParser = data => {
    const { pagePath, pageVar, pageInput, isPage, member, blocks, blockInfo, formInfo, pageCommonSql, pageNativeSql, originCode, lodashFns, utilFns, pageActionInfo = [], remoteOptions = false, initCommonSqlQuery = false, picklists = false, utilFunctions = [], actionName, pageName, propsChangeState, } = data;
    let async = false;
    const jsObj = {}; // 暂时不支持javascript(...)语句
    const innerParam = [];
    const formValidInfo = formInfo.map(formName => `${formName}.valid`);
    // 路由跳转需要引入 Fishx
    const fishxFns = [];
    function isListType(name) {
        const type = pageVar.find(v => v.name === name && !v.isCommonSql)
            ? pageVar.find(v => v.name === name && !v.isCommonSql).type
            : '';
        return type.split(' ').indexOf('List') !== -1;
    }
    function isPageVar(name) {
        return pageVar.findIndex(v => v.name === name && !v.isCommonSql) !== -1;
    }
    function isPageInput(name) {
        return pageInput.findIndex(v => v.name === name) !== -1;
    }
    function isCommonSql(name) {
        return ((pageCommonSql.findIndex(v => v.name === name) !== -1 ||
            pageNativeSql.findIndex(v => v.name === name) !== -1) &&
            queryArr.findIndex(v => v.name === name) === -1);
    }
    function ast2String(node, res) {
        if (t.isMemberExpression(node.object)) {
            ast2String(node.object, res);
        }
        else {
            res.push(node.object.name);
        }
        t.isIdentifier(node.property)
            ? res.push(node.property.name)
            : res.push(node.property);
    }
    function getActualNode(node) {
        var _a;
        let newNode = node;
        if (t.isIdentifier(node)) {
            if (!innerParam.includes(node.name)) {
                if (isPageVar(node.name)) {
                    newNode = (0, utils_1.objValueStr2AST)(`this.state.${node.name}`);
                }
                if (isPageInput(node.name)) {
                    newNode = isPage
                        ? (0, utils_1.objValueStr2AST)(`this.props.match.params.${node.name}`)
                        : (0, utils_1.objValueStr2AST)(`this.props.${node.name}`);
                }
            }
        }
        if (t.isMemberExpression(node)) {
            const rightArr = [];
            ast2String(node, rightArr);
            if (!innerParam.includes(rightArr[0])) {
                const newObjStr = (_a = generator(node.object)) === null || _a === void 0 ? void 0 : _a.code;
                if (newObjStr && (isPageVar(rightArr[0]) || isCommonSql(rightArr[0]))) {
                    newNode.object = (0, utils_1.objValueStr2AST)(`this.state.${newObjStr}`);
                }
                if (newObjStr && isPageInput(rightArr[0])) {
                    newNode.object = isPage
                        ? (0, utils_1.objValueStr2AST)(`this.props.match.params.${newObjStr}`)
                        : (0, utils_1.objValueStr2AST)(`this.props.${newObjStr}`);
                }
            }
            // if (isCommonSql(rightArr[0])) {
            //   const commonSqlName = rightArr.join('.');
            //   if (commonSqlName.indexOf('.Current') !== -1) {
            //     const varArr = commonSqlName.split('.List.Current');
            //     newNode = objValueStr2AST(`this.state.${varArr[0]}_current${varArr[1]}`);
            //   } else {
            //     const varArr = commonSqlName.split('.List');
            //     newNode = objValueStr2AST(`this.state.${varArr[0]}${varArr[1]}`);
            //   }
            // }
        }
        return newNode;
    }
    function getNativeSqlParam(sqlData) {
        var _a, _b;
        const propArr = [];
        (_a = sqlData.params) === null || _a === void 0 ? void 0 : _a.forEach(v => {
            propArr.push(t.objectProperty(t.identifier(v), (0, utils_1.objValueStr2AST)(`this.state.${v}`)));
        });
        (_b = Object.keys(sqlData.pageInfo)) === null || _b === void 0 ? void 0 : _b.forEach(key => {
            const valueNode = isNaN(Number(sqlData.pageInfo[key]))
                ? (0, utils_1.objValueStr2AST)(`this.state.${sqlData.pageInfo[key]}`)
                : t.numericLiteral(Number(sqlData.pageInfo[key]));
            propArr.push(t.objectProperty(t.identifier(key), valueNode));
        });
        return t.objectExpression(propArr);
    }
    function getCommonSqlParam(sqlData, path) {
        const propArr = [];
        let inPageChange = false;
        const fnPath = path.findParent(path => path.isFunctionDeclaration());
        fnPath.node.params.forEach(v => {
            if (t.isIdentifier(v) && v.name === 'PaginationItem') {
                inPageChange = true;
            }
        });
        sqlData.testValue.forEach(v => {
            let varName;
            let newExp;
            v.placehold.replace(/#{([\s\S]*?)}/g, (match, key) => {
                varName = key.split('-')[1];
            });
            if (v.varType === 'page') {
                newExp = v.expression.replace(varName, `this.state.${varName}`);
            }
            else if (v.varType === 'input') {
                newExp = isPage
                    ? v.expression.replace(varName, `this.props.match.params.${varName}`)
                    : v.expression.replace(varName, `this.props.${varName}`);
            }
            else {
                newExp = v.expression;
            }
            propArr.push(t.objectProperty(t.identifier(varName), t.identifier(newExp)));
        });
        if (typeof sqlData.pageSize === 'string' &&
            typeof sqlData.pageIndex === 'string') {
            let pageSize;
            let pageIndex;
            sqlData.pageSize.replace(/#{([\s\S]*?)}/g, (match, key) => {
                pageSize = key;
            });
            sqlData.pageIndex.replace(/#{([\s\S]*?)}/g, (match, key) => {
                pageIndex = key;
            });
            if (pageSize) {
                propArr.push(t.objectProperty(t.identifier('pageSize'), inPageChange
                    ? (0, utils_1.objValueStr2AST)('PaginationItem.pageSize')
                    : (0, utils_1.objValueStr2AST)(`this.state.${pageSize}`)));
            }
            if (pageIndex) {
                propArr.push(t.objectProperty(t.identifier('pageIndex'), inPageChange
                    ? (0, utils_1.objValueStr2AST)('PaginationItem.currentPage')
                    : (0, utils_1.objValueStr2AST)(`this.state.${pageIndex}`)));
            }
        }
        return t.objectExpression(propArr);
    }
    function handleFormValidNode(node) {
        let { code } = generator(node);
        let formValidExist;
        formValidInfo.forEach((formName, index) => {
            if (code.includes(formName) && !code.includes(`await lowcode_formValid(this, "${formName}")`)) {
                formValidExist = true;
                const awaitNode = t.awaitExpression(t.callExpression(t.identifier('lowcode_formValid'), [
                    t.thisExpression(),
                    t.stringLiteral(formName.split('.')[0]),
                ]));
                const { code: awaitCode } = generator(awaitNode);
                code = code.replace(formName, awaitCode);
            }
        });
        if (formValidExist) {
            try {
                const codeAst = parser.parse(code, {
                    plugins: ['typescript'],
                    allowAwaitOutsideFunction: true,
                });
                return codeAst.program.body[0].expression;
            }
            catch (error) {
                return null;
            }
        }
        return null;
    }
    let queryArr = [];
    const actionLodashFns = [];
    try {
        const originAst = parser.parse(originCode, {
            plugins: ['typescript'],
        });
        (0, traverse_1.default)(originAst, {
            FunctionDeclaration(path) {
                path.node.params.forEach(v => {
                    if (innerParam.indexOf(v.name) === -1) {
                        innerParam.push(v.name);
                    }
                });
            },
            VariableDeclarator(path) {
                const parmaName = path.node.id.name;
                if (innerParam.indexOf(parmaName) === -1) {
                    innerParam.push(parmaName);
                }
            },
            CallExpression(path) {
                const calleeNode = path.node.callee;
                const params = path.node.arguments;
                if (t.isIdentifier(calleeNode) && calleeNode.name === 'javascript') {
                    const uid = `javascript_${(0, utils_1.getRandomStr)()}`;
                    const jsContent = params[0].quasis[0].value.raw;
                    jsObj[uid] = jsContent;
                    path.replaceWith(t.identifier(uid));
                }
                else if (t.isMemberExpression(calleeNode) &&
                    t.isIdentifier(calleeNode.object) &&
                    !t.isVariableDeclarator(path.parentPath.node)) {
                    const fn = calleeNode.property.name;
                    if (calleeNode.object.name === 'query' &&
                        queryArr.findIndex(v => v.name === fn) === -1) {
                        queryArr.push({ name: fn, type: (0, utils_1.camelize)(`_${fn}`) });
                    }
                }
            },
        });
        // 暂时不支持javascript(...)语句
        // const originRes = generator(originAst);
        // let preCode = originRes.code;
        // for (const key in jsObj) {
        //   if (Object.prototype.hasOwnProperty.call(jsObj, key)) {
        //     const element = jsObj[key];
        //     preCode = preCode.replace(key, element);
        //   }
        // }
        // const ast = parser.parse(preCode, {
        //   plugins: ['typescript'],
        // });
        (0, traverse_1.default)(originAst, {
            ForOfStatement(path) {
                const forData = path.node.right;
                const forItem = path.node.left;
                const forBlocks = path.node.body.body;
                const { start, end, loc } = path.node || {};
                forBlocks.unshift(t.expressionStatement(t.assignmentExpression('=', forItem, t.memberExpression(forData, t.identifier('index'), true))));
                path.replaceWith(t.forStatement(t.variableDeclaration('let', [
                    t.variableDeclarator(t.identifier('index'), t.numericLiteral(0)),
                ]), t.binaryExpression('<', t.identifier('index'), t.memberExpression(forData, t.identifier('length'))), t.updateExpression('++', t.identifier('index'), false), t.blockStatement(forBlocks)));
                path.node.start = start;
                path.node.end = end;
                path.node.loc = loc;
            },
            CallExpression(path) {
                const calleeNode = path.node.callee;
                const params = path.node.arguments;
                if (t.isMemberExpression(calleeNode) &&
                    t.isIdentifier(calleeNode.object)) {
                    const fn = calleeNode.property.name;
                    const ctx = calleeNode.object.name;
                    if (ctx === 'server') {
                        params.unshift(t.stringLiteral(fn));
                        if (t.isVariableDeclarator(path.parentPath.node)) {
                            path.node.callee = t.identifier('call');
                            path.node.arguments = params;
                        }
                        else {
                            path.replaceWith(t.assignmentExpression('=', t.identifier(fn), t.callExpression(t.identifier('call'), params)));
                        }
                        if (utilFns.indexOf('call') === -1) {
                            utilFns.push('call');
                        }
                    }
                    else if (ctx === 'query') {
                        let activeMethod = 'get';
                        if (pageNativeSql.find(v => v.name === fn)) {
                            activeMethod = 'nativeGet';
                        }
                        if (t.isVariableDeclarator(path.parentPath.node)) {
                            path.node.callee = t.identifier(activeMethod);
                            path.node.arguments = [t.stringLiteral(fn)];
                        }
                        else {
                            path.replaceWith(t.assignmentExpression('=', t.identifier(fn), t.callExpression(t.identifier(activeMethod), [
                                t.stringLiteral(fn),
                            ])));
                        }
                        if (utilFns.indexOf(activeMethod) === -1) {
                            utilFns.push(activeMethod);
                        }
                    }
                    else if (ctx === 'popup' && fn === 'message') {
                        const msgType = params[0].property.name;
                        let newType;
                        switch (msgType) {
                            case 'SUCCESS':
                                newType = 'success';
                                break;
                            case 'WARN':
                                newType = 'warn';
                                break;
                            case 'ERROR':
                                newType = 'error';
                                break;
                            case 'INFO':
                                newType = 'info';
                                break;
                            default:
                                break;
                        }
                        path.node.arguments = params.slice(1);
                        path.node.callee = t.memberExpression(t.identifier('message'), t.identifier(newType));
                    }
                    else if (formMethods.includes(fn) || modalMethods.includes(fn)) {
                        path.node.callee.object = (0, utils_1.objValueStr2AST)(`this.${ctx}.current`);
                    }
                }
                else if (t.isIdentifier(calleeNode)) {
                    if (calleeNode.name === 'goto') {
                        // TODO: 临时处理 goto 节点入参 改为 pages.pageName
                        if (params[0] && t.isMemberExpression(params[0])) {
                            const paramsArr = [];
                            let paramsStr = '';
                            for (let i = 1; i < params.length; i += 1) {
                                const curParam = generator(params[i]);
                                paramsArr.push(`$\{${curParam.code}}`);
                            }
                            if (paramsArr.length > 0)
                                paramsStr = paramsArr.join('/');
                            let newParma = params[0].property.name === 'index'
                                ? `/${paramsStr}`
                                : `/${params[0].property.name}/${paramsStr}`;
                            newParma = t.templateLiteral([t.templateElement({ raw: newParma })], []);
                            path.node.arguments = [newParma];
                        }
                        path.node.callee = (0, utils_1.objValueStr2AST)('Fishx.history.push');
                        fishxFns.push('Fishx');
                    }
                    else if (calleeNode.name === 'eventDispatch') {
                        const eventName = params[0].value;
                        path.node.callee = (0, utils_1.objValueStr2AST)(`this.props.${eventName}`);
                        const newParams = [];
                        const oldParams = params.pop();
                        oldParams.properties.forEach(v => {
                            newParams.push(v.value);
                        });
                        path.node.arguments = newParams;
                    }
                    else if (utilFunctions.includes(calleeNode.name)) {
                        let newFn = calleeNode.name;
                        if (newFn[0] === '_') {
                            newFn = newFn.slice(1);
                            if (lodashFns.indexOf(newFn) === -1) {
                                lodashFns.push(newFn);
                            }
                            if (actionLodashFns.indexOf(newFn) === -1) {
                                actionLodashFns.push(newFn);
                            }
                            path.replaceWith(t.callExpression(t.identifier(newFn), params));
                        }
                        else if (utilFns.indexOf(newFn) === -1) {
                            utilFns.push(newFn);
                        }
                    }
                }
            },
        });
        // const firstRes = generator(ast);
        // let firstCode = firstRes.code;
        // for (const key in jsObj) {
        //   if (Object.prototype.hasOwnProperty.call(jsObj, key)) {
        //     const element = jsObj[key];
        //     firstCode = firstCode.replace(key, element);
        //   }
        // }
        // const secondAst = parser.parse(firstRes.code, {
        //   plugins: ['typescript'],
        // });
        (0, traverse_1.default)(originAst, {
            FunctionDeclaration(path) {
                path.traverse({
                    Identifier(path) {
                        if (!t.isMemberExpression(path.parentPath.node) &&
                            !t.isFunctionDeclaration(path.parentPath.node) &&
                            !t.isOptionalMemberExpression(path.parentPath.node) &&
                            !t.isAssignmentExpression(path.parentPath.node) &&
                            !(t.isObjectProperty(path.parentPath.node) &&
                                path.parentPath.node.key.start === path.node.start)) {
                            const newNode = getActualNode(path.node);
                            path.replaceWith(newNode);
                        }
                    },
                    MemberExpression(path) {
                        if (!t.isAssignmentExpression(path.parentPath.node)) {
                            let ifTrans = true;
                            if (t.isMemberExpression(path.parentPath.node)) {
                                ifTrans = false;
                                const arr = [];
                                ast2String(path.node, arr);
                                if ((isCommonSql(arr[0]) || isPageVar(arr[0])) &&
                                    arr.indexOf('Current') === -1 &&
                                    path.parentPath.node.property.name !== 'Current') {
                                    ifTrans = true;
                                }
                            }
                            if (ifTrans) {
                                const newNode = getActualNode(path.node);
                                path.replaceWith(newNode);
                            }
                        }
                    },
                    CallExpression(path) {
                        var _a, _b, _c, _d;
                        if (t.isIdentifier(path.node.callee) &&
                            path.node.callee.name === 'RefreshData') {
                            async = true;
                            let sqlName;
                            if (t.isStringLiteral(path.node.arguments[0])) {
                                sqlName = path.node.arguments[0].value;
                            }
                            else if (t.isMemberExpression(path.node.arguments[0])) {
                                sqlName = path.node.arguments[0].property.name;
                            }
                            const sqlObj = pageCommonSql.find(v => v.name === sqlName);
                            const sqlData = sqlObj ? JSON.parse(sqlObj.data) : null;
                            const { start, end, loc } = path.node || {};
                            const nodeIndex = ((_d = (_c = (_b = (_a = path.parentPath) === null || _a === void 0 ? void 0 : _a.parentPath) === null || _b === void 0 ? void 0 : _b.node) === null || _c === void 0 ? void 0 : _c.body) === null || _d === void 0 ? void 0 : _d.findIndex(curNode => curNode.start === start)) || 0;
                            if (sqlData) {
                                const paramExp = getCommonSqlParam(sqlData, path);
                                path.replaceWithMultiple([
                                    t.variableDeclaration('let', [
                                        t.variableDeclarator(t.identifier(`${sqlName}_res`), t.awaitExpression(t.callExpression(t.identifier('get'), [
                                            t.stringLiteral(sqlName),
                                            paramExp,
                                            t.identifier('QueryMap'),
                                        ]))),
                                    ]),
                                    t.expressionStatement(t.assignmentExpression('=', t.identifier(sqlName), t.identifier(`${sqlName}_res`))),
                                ]);
                            }
                            else {
                                // RefreshData 调用 nativeSql
                                const sqlObj = pageNativeSql.find(v => v.name === sqlName);
                                const sqlData = sqlObj ? JSON.parse(sqlObj.data) : [];
                                const paramExp = getNativeSqlParam(sqlData);
                                path.replaceWithMultiple([
                                    t.variableDeclaration('let', [
                                        t.variableDeclarator(t.identifier(`${sqlName}_res`), t.awaitExpression(t.callExpression(t.identifier('nativeGet'), [
                                            t.stringLiteral(sqlName),
                                            paramExp,
                                            t.identifier('QueryMap'),
                                        ]))),
                                    ]),
                                    t.expressionStatement(t.assignmentExpression('=', t.identifier(sqlName), t.identifier(`${sqlName}_res`))),
                                ]);
                                utilFns.push('nativeGet');
                            }
                            path.parentPath.parentPath.node.body[nodeIndex].start = start;
                            path.parentPath.parentPath.node.body[nodeIndex].end = end;
                            path.parentPath.parentPath.node.body[nodeIndex].loc = loc;
                        }
                        else if (t.isIdentifier(path.node.callee) &&
                            ['call', 'get', 'nativeGet'].indexOf(path.node.callee.name) !==
                                -1 &&
                            !t.isAwaitExpression(path.parentPath.node)) {
                            async = true;
                            if (path.node.callee.name === 'get') {
                                const sqlName = path.node.arguments[0].value;
                                const sqlObj = pageCommonSql.find(v => v.name === sqlName);
                                const sqlData = sqlObj ? JSON.parse(sqlObj.data) : {};
                                const paramExp = getCommonSqlParam(sqlData, path);
                                path.node.arguments.push(paramExp);
                                path.node.arguments.push(t.identifier('QueryMap'));
                            }
                            if (path.node.callee.name === 'nativeGet') {
                                const sqlName = path.node.arguments[0].value;
                                const sqlObj = pageNativeSql.find(v => v.name === sqlName);
                                const sqlData = sqlObj ? JSON.parse(sqlObj.data) : {};
                                const paramExp = getNativeSqlParam(sqlData);
                                path.node.arguments.push(paramExp);
                                path.node.arguments.push(t.identifier('QueryMap'));
                            }
                            path.replaceWith(t.awaitExpression(path.node));
                        }
                        else if (t.isMemberExpression(path.node.callee) &&
                            path.node.callee.object.name === 'popup' &&
                            path.node.callee.property.name === 'confirm' &&
                            !t.isAwaitExpression(path.parentPath.node)) {
                            if (path.node.arguments.length === 3) {
                                if (member.component.indexOf('Modal') === -1) {
                                    member.component.push('Modal');
                                }
                                const type = path.node.arguments[2].property.name;
                                let newType;
                                switch (type) {
                                    case 'SUCCESS':
                                        newType = 'success';
                                        break;
                                    case 'WARN':
                                        newType = 'warning';
                                        break;
                                    case 'ERROR':
                                        newType = 'error';
                                        break;
                                    case 'INFO':
                                        newType = 'info';
                                        break;
                                    default:
                                        break;
                                }
                                path.node.callee = (0, utils_1.objValueStr2AST)(`Modal.${newType}`);
                                path.node.arguments = [
                                    t.objectExpression([
                                        t.objectProperty(t.identifier('title'), path.node.arguments[0]),
                                        t.objectProperty(t.identifier('content'), path.node.arguments[1]),
                                    ]),
                                ];
                            }
                            else {
                                if (utilFns.indexOf('popup') === -1) {
                                    utilFns.push('popup');
                                }
                                async = true;
                                path.replaceWith(t.awaitExpression(path.node));
                            }
                        }
                        else if (t.isMemberExpression(path.node.callee) &&
                            path.node.callee.object.name === 'client') {
                            path.node.callee.object = t.thisExpression();
                            const fn = path.node.callee.property.name;
                            const actionInfo = pageActionInfo.find(v => v.name === fn);
                            if (actionInfo && actionInfo.async) {
                                async = true;
                                path.replaceWith(t.awaitExpression(path.node));
                            }
                        }
                        else if (t.isMemberExpression(path.node.callee) &&
                            blockInfo.find(v => v.ref === path.node.callee.object.name)) {
                            const blockName = blockInfo.find(v => v.ref === path.node.callee.object.name).name;
                            const fn = path.node.callee.property.name;
                            const res = blocks.find(v => v.name === blockName);
                            let blockActionInfo;
                            if (res && res.blockData) {
                                blockActionInfo = res.blockData.actions.find(v => v.name === fn);
                            }
                            path.node.callee.object = (0, utils_1.objValueStr2AST)(`this.${path.node.callee.object.name}.current`);
                            if (blockActionInfo && blockActionInfo.async) {
                                async = true;
                                path.replaceWith(t.awaitExpression(path.node));
                            }
                        }
                    },
                });
                path.node.async = async;
            },
        });
        // const secondRes = generator(secondAst);
        // const thirdAst = parser.parse(secondRes.code, {
        //   plugins: ['typescript'],
        // });
        const transRes = {};
        (0, traverse_1.default)(originAst, {
            Program(path) {
                const nodeLists = path.node.body;
                // 引入 fishx 工具函数
                if (fishxFns.length) {
                    const fishxTools = [];
                    fishxFns.forEach(v => {
                        fishxTools.push(t.importSpecifier(t.identifier(v), t.identifier(v)));
                    });
                    nodeLists.unshift(t.importDeclaration(fishxTools, t.stringLiteral('fishx')));
                }
                // 引入lodash函数
                actionLodashFns.forEach(fn => {
                    nodeLists.unshift(t.importDeclaration([t.importDefaultSpecifier(t.identifier(fn))], t.stringLiteral(`lodash/${fn}`)));
                });
                // 引入@whalecloud/fdx组件
                nodeLists.unshift(t.importDeclaration([
                    t.importSpecifier(t.identifier('message'), t.identifier('message')),
                    t.importSpecifier(t.identifier('Modal'), t.identifier('Modal')),
                ], t.stringLiteral('antd')));
                nodeLists.unshift(t.importDeclaration([
                    t.importSpecifier(t.identifier('QueryMap'), t.identifier('QueryMap')),
                ], t.stringLiteral(`@/types/${pageName}`)));
                nodeLists.unshift(t.importDeclaration([t.importSpecifier(t.identifier('List'), t.identifier('List'))], t.stringLiteral('@/utils/ProjectType')));
                if (utilFns.length) {
                    const importUtils = [];
                    utilFns.forEach(v => {
                        importUtils.push(t.importSpecifier(t.identifier(v), t.identifier(v)));
                    });
                    nodeLists.unshift(t.importDeclaration(importUtils, t.stringLiteral('@/utils/util')));
                }
                // export action函数
                nodeLists.push(t.exportDefaultDeclaration(t.identifier(actionName)));
                // 末尾添加sourceMappingURL
                // TODO: 与vite不兼容暂时注释
                // const lastNode = nodeLists[path.node.body.length - 1];
                // t.addComment(lastNode, 'trailing', ' export  \n', true);
                // t.addComment(
                //   lastNode,
                //   'trailing',
                //   `# sourceMappingURL=${actionName}.ts.map`,
                //   true
                // );
            },
            FunctionDeclaration(path) {
                path.traverse({
                    IfStatement(path) {
                        const newNode = handleFormValidNode(path.node.test);
                        if (newNode) {
                            async = true;
                            path.node.test = newNode;
                        }
                    },
                    AssignmentExpression(path) {
                        const leftNode = path.node.left;
                        let rightNode = path.node.right;
                        const newNode = handleFormValidNode(rightNode);
                        if (newNode) {
                            async = true;
                            path.node.right = newNode;
                            rightNode = newNode;
                        }
                        if (t.isIdentifier(leftNode)) {
                            if (isPageVar(leftNode.name) || isCommonSql(leftNode.name)) {
                                let newRightNode;
                                if (isListType(leftNode.name)) {
                                    // newRightNode = t.newExpression(t.identifier('List'), [newRightNode])
                                    newRightNode = rightNode;
                                }
                                else {
                                    newRightNode = getActualNode(rightNode);
                                }
                                async = true;
                                const stateExp = [t.objectProperty(leftNode, newRightNode)];
                                // 如果页面变量受传入的props值影响，则更新该页面状态时，同时还要更新innerUpdate这个内置的状态(getDerivedStateFromProps)
                                if (propsChangeState.findIndex(v => v.state === leftNode.name) !==
                                    -1) {
                                    stateExp.push(t.objectProperty(t.identifier('innerUpdate'), t.booleanLiteral(true)));
                                }
                                path.replaceWith(t.awaitExpression(t.callExpression(t.identifier('setStatePromise'), [
                                    t.thisExpression(),
                                    t.objectExpression(stateExp),
                                ])));
                            }
                            else {
                                path.node.right = getActualNode(rightNode);
                            }
                        }
                        else if (t.isMemberExpression(leftNode)) {
                            const leftArr = [];
                            ast2String(leftNode, leftArr);
                            if (isPageVar(leftArr[0])) {
                                async = true;
                                if (leftArr.includes('Current')) {
                                    const rightExp = leftArr.length === 2
                                        ? t.newExpression(t.identifier('List'), [
                                            (0, utils_1.objValueStr2AST)(`this.state.${leftArr[0]}`),
                                            getActualNode(rightNode),
                                        ])
                                        : t.newExpression(t.identifier('List'), [
                                            (0, utils_1.objValueStr2AST)(`this.state.${leftArr[0]}`),
                                            (0, utils_1.key2ObjCall)(leftArr.slice(2), getActualNode(rightNode), `this.state.${leftArr[0]}`),
                                        ]);
                                    path.replaceWith(t.awaitExpression(t.callExpression(t.identifier('setStatePromise'), [
                                        t.thisExpression(),
                                        t.objectExpression([
                                            (0, utils_1.objPropStr2AST)(leftArr[0], rightExp),
                                        ]),
                                    ])));
                                }
                                else {
                                    const isComputed = leftNode.computed;
                                    const newLeftNode = typeof leftArr[1] === 'string'
                                        ? t.identifier(leftArr[1])
                                        : leftArr[1];
                                    const stateExp = [
                                        t.objectProperty(t.identifier(leftArr[0]), t.objectExpression([
                                            t.spreadElement((0, utils_1.objValueStr2AST)(`prev.${leftArr[0]}`)),
                                            t.objectProperty(newLeftNode, getActualNode(rightNode), isComputed),
                                        ])),
                                    ];
                                    // 如果页面变量受传入的props值影响，则更新该页面状态时，同时还要更新innerUpdate这个内置的状态(getDerivedStateFromProps)
                                    if (propsChangeState.findIndex(v => v.state === leftArr[0]) !== -1) {
                                        stateExp.push(t.objectProperty(t.identifier('innerUpdate'), t.booleanLiteral(true)));
                                    }
                                    path.replaceWith(t.awaitExpression(t.callExpression(t.identifier('setStatePromise'), [
                                        t.thisExpression(),
                                        t.arrowFunctionExpression([t.identifier('prev')], t.blockStatement([
                                            t.returnStatement(t.objectExpression(stateExp)),
                                        ])),
                                    ])));
                                }
                            }
                            else if (isCommonSql(leftArr[0])) {
                                async = true;
                                let rightExp;
                                const sqlname = leftArr[0];
                                if (leftArr.length === 2) {
                                    rightExp = t.newExpression(t.identifier('List'), [
                                        getActualNode(rightNode),
                                        t.memberExpression(getActualNode(rightNode), t.numericLiteral(0), true),
                                    ]);
                                }
                                else if (leftArr.length === 3) {
                                    rightExp = t.newExpression(t.identifier('List'), [
                                        (0, utils_1.objValueStr2AST)(`this.state.${sqlname}.List`),
                                        getActualNode(rightNode),
                                    ]);
                                }
                                else {
                                    rightExp = t.newExpression(t.identifier('List'), [
                                        (0, utils_1.objValueStr2AST)(`this.state.${sqlname}.List`),
                                        (0, utils_1.key2ObjCall)(leftArr.slice(2), getActualNode(rightNode), `this.state.${sqlname}.List`),
                                    ]);
                                }
                                const stateExp = (0, utils_1.objPropStr2AST)(`${sqlname}.List`, rightExp);
                                path.replaceWith(t.awaitExpression(t.callExpression(t.identifier('setStatePromise'), [
                                    t.thisExpression(),
                                    t.objectExpression([stateExp]),
                                ])));
                            }
                            else {
                                path.node.right = getActualNode(rightNode);
                            }
                        }
                        else {
                            path.node.right = getActualNode(rightNode);
                        }
                    },
                    CallExpression(path) {
                        path.node.arguments.forEach((arg, index) => {
                            const newNode = handleFormValidNode(arg);
                            if (newNode) {
                                async = true;
                                path.node.arguments[index] = newNode;
                            }
                        });
                    },
                    SwitchStatement(path) {
                        const newNode = handleFormValidNode(path.node.discriminant);
                        if (newNode) {
                            async = true;
                            path.node.discriminant = newNode;
                        }
                    },
                });
                if (initCommonSqlQuery && actionName === 'mounted') {
                    path.node.body.body.unshift(t.expressionStatement(t.callExpression((0, utils_1.objValueStr2AST)('this.atStart'), [])));
                }
                if (picklists && actionName === 'mounted') {
                    path.node.body.body.unshift(t.expressionStatement(t.callExpression((0, utils_1.objValueStr2AST)('this.fetchPicklists'), [])));
                }
                if (remoteOptions && actionName === 'mounted') {
                    path.node.body.body.unshift(t.expressionStatement(t.callExpression((0, utils_1.objValueStr2AST)('this.fetchRemoteOptions'), [])));
                }
                queryArr.forEach(v => {
                    const varExp = t.identifier(v.name);
                    varExp.typeAnnotation = t.tsTypeAnnotation(t.tsTypeReference(t.identifier(v.type)));
                    path.node.body.body.unshift(t.variableDeclaration('let', [t.variableDeclarator(varExp)]));
                });
                transRes.actionName = actionName;
                transRes.async = async;
                transRes.params = path.node.params;
                transRes.body = path.node.body;
            },
        });
        (0, traverse_1.default)(originAst, {
            FunctionDeclaration(path) {
                // transform to async function
                if (async && !path.node.async) {
                    path.replaceWith(t.functionDeclaration(path.node.id, path.node.params, path.node.body, false, // generator
                    true // async
                    ));
                }
            },
        });
        const output = generator(originAst, {
            sourceMaps: true,
            sourceFileName: `${pagePath}/${actionName}.ts`,
        }, originCode);
        if (Object.keys(jsObj).length > 0) {
            for (const key in jsObj) {
                if (Object.prototype.hasOwnProperty.call(jsObj, key)) {
                    const element = jsObj[key];
                    output.code = output.code.replace(key, element);
                }
            }
        }
        transRes.generatedAction = output;
        return transRes;
    }
    catch (error) {
        console.error(error);
        error.parseCode = originCode;
        throw error;
    }
};
exports.default = logicParser;
