"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = ({ types: t, }) => {
    return {
        pre() {
            this.movedStatements = [];
            this.functionDeclarations = [];
            this.hasFinishedMoving = false;
            this.addedCompletionRecords = false;
            this.variables = [];
        },
        visitor: {
            Statement(path) {
                if (this.hasFinishedMoving)
                    return;
                if (path.isDeclaration() && !path.getFunctionParent()) {
                    if (path.isVariableDeclaration()) {
                        if (path.parentPath.isProgram() || path.node.kind === 'var') {
                            const asAssignments = [];
                            for (const decl of path.node.declarations) {
                                if (decl.id.name ===
                                    this.completionRecordId.name)
                                    return;
                                this.variables.push(decl.id.name);
                                if (decl.init) {
                                    const expr = t.assignmentExpression('=', decl.id, decl.init);
                                    asAssignments.push(t.variableDeclaration('const', [
                                        t.variableDeclarator(path.scope.generateUidIdentifier('v'), expr),
                                    ]));
                                }
                            }
                            if (path.parentPath.isProgram()) {
                                this.movedStatements.push(...asAssignments);
                                path.remove();
                            }
                            else {
                                path.replaceWithMultiple(asAssignments);
                            }
                            return;
                        }
                    }
                    else if (path.isFunctionDeclaration()) {
                        this.functionDeclarations.push(path.node);
                        if (path.node.id) {
                            path.replaceWith(t.expressionStatement(path.node.id));
                        }
                        else {
                            path.remove();
                        }
                        return;
                    }
                    else if (path.isClassDeclaration() &&
                        path.parentPath.isProgram() &&
                        path.node.id) {
                        this.variables.push(path.node.id.name);
                        this.movedStatements.push(t.expressionStatement(t.assignmentExpression('=', path.node.id, t.classExpression(path.node.id, path.node.superClass, path.node.body))));
                        path.replaceWith(t.expressionStatement(path.node.id));
                        return;
                    }
                }
                if (path.isExpressionWrapper() &&
                    !path.getFunctionParent() &&
                    !((path.isExpressionStatement() &&
                        path.node.expression.type === 'AssignmentExpression' &&
                        path.node.expression.left.type === 'Identifier' &&
                        path.node.expression.left.name === this.completionRecordId.name))) {
                    path.replaceWith(t.expressionStatement(t.assignmentExpression('=', this.completionRecordId, path.node.expression)));
                    return;
                }
                if (path.parentPath.isProgram()) {
                    this.movedStatements.push(path.node);
                }
            },
            Program: {
                enter(path) {
                    if (this.hasFinishedMoving)
                        return;
                    this.completionRecordId = path.scope.generateUidIdentifier('cr');
                    if (path.node.directives.length === 1 &&
                        path.node.directives[0].value.type === 'DirectiveLiteral' &&
                        path.node.body.length === 0) {
                        path.replaceWith(t.program([
                            t.expressionStatement({
                                ...path.node.directives[0].value,
                                type: 'StringLiteral',
                            }),
                        ]));
                    }
                },
                exit(path) {
                    if (this.hasFinishedMoving)
                        return;
                    this.hasFinishedMoving = true;
                    path.replaceWith(t.program([
                        ...this.variables.map((v) => t.variableDeclaration('var', [
                            t.variableDeclarator(t.identifier(v)),
                        ])),
                        ...this.functionDeclarations,
                        t.expressionStatement(t.callExpression(t.arrowFunctionExpression([], t.blockStatement([
                            t.variableDeclaration('var', [
                                t.variableDeclarator(this.completionRecordId),
                            ]),
                            ...this.movedStatements,
                            t.returnStatement(this.completionRecordId),
                        ])), [])),
                    ], path.node.directives));
                },
            },
        },
    };
};
//# sourceMappingURL=wrap-as-iife.js.map