"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.rxjs7Upgrade = void 0;
const ast_utils_1 = require("@schematics/angular/utility/ast-utils");
const change_1 = require("@schematics/angular/utility/change");
const path_1 = require("path");
const ts = require("typescript");
const typescript_1 = require("../utilities/typescript");
const workspace_1 = require("../utilities/workspace");
function rxjs7Upgrade(options) {
    return (tree) => __awaiter(this, void 0, void 0, function* () {
        const path = options.path || '/';
        const workspace = yield (0, workspace_1.getWorkspace)(path, tree);
        // Get all tsconfig paths from the workspace, including test tsconfigs
        const tsConfigPaths = (0, workspace_1.getTsConfigPaths)(workspace, tree);
        // The base path in the file system for the path argument, replacing all backslashes with forward slashes (for cross-system compatibility).
        // The absolute file system path is needed for the typescript compiler to resolve files correctly. 
        const basePath = process.cwd().replace(/\\/g, path);
        tsConfigPaths.forEach(tsConfigPath => {
            const program = (0, typescript_1.createTsProgram)(tree, tsConfigPath, basePath);
            const checker = program.getTypeChecker();
            for (const sourceFile of program.getSourceFiles()) {
                // Skip declaration files and external library files
                if (sourceFile.isDeclarationFile || program.isSourceFileFromExternalLibrary(sourceFile)) {
                    continue;
                }
                const observableSymbols = ['Observable', 'Subject', 'BehaviorSubject', 'ReplaySubject', 'AsyncSubject'];
                const toPromiseCalls = (0, ast_utils_1.findNodes)(sourceFile, ts.isCallExpression, undefined, true).filter(node => {
                    if (ts.isPropertyAccessExpression(node.expression) && node.expression.name.text === 'toPromise') {
                        const symbol = checker.getTypeAtLocation(node.expression.expression).symbol;
                        return symbol && observableSymbols.includes(symbol.name);
                    }
                    return false;
                });
                if (toPromiseCalls.length) {
                    const fileToEdit = (0, path_1.relative)(basePath, sourceFile.fileName);
                    const recorder = tree.beginUpdate(fileToEdit);
                    const changes = [];
                    const printer = ts.createPrinter();
                    // Add import for lastValueFrom
                    changes.push((0, ast_utils_1.insertImport)(sourceFile, fileToEdit, 'lastValueFrom', 'rxjs'));
                    // Replace toPromise calls with lastValueFrom
                    toPromiseCalls.forEach(node => {
                        if (ts.isPropertyAccessExpression(node.expression)) {
                            const newCallExpression = ts.factory.createCallExpression(ts.factory.createIdentifier('lastValueFrom'), undefined, [node.expression.expression]);
                            const newNodeText = printer.printNode(ts.EmitHint.Unspecified, newCallExpression, sourceFile);
                            const change = new change_1.ReplaceChange(fileToEdit, node.getStart(), node.getText(), newNodeText);
                            changes.push(change);
                        }
                    });
                    (0, change_1.applyToUpdateRecorder)(recorder, changes);
                    tree.commitUpdate(recorder);
                }
            }
        });
    });
}
exports.rxjs7Upgrade = rxjs7Upgrade;
//# sourceMappingURL=index.js.map