"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Add = void 0;
const core_1 = require("@oclif/core");
const ts_morph_1 = require("ts-morph");
const _cliter_1 = require("../@cliter");
const common_1 = require("../@cliter/functions/common");
const code_writer_1 = require("../@cliter/utils/code-writer");
class Add extends core_1.Command {
    async run() {
        const { args, flags } = await this.parse(Add);
        const { packageName } = await _cliter_1.Prompter.promptAddPackage(args.firstArg);
        // define state like a generate command
        const addCommandState = {
            command: this,
            flags,
            packageName,
        };
        if (args.firstArg === _cliter_1.Scope.BACK) {
            switch (packageName) {
                case 'auditing': {
                    await _cliter_1.BackHandler.addPackage(addCommandState);
                    core_1.ux.action.start('Installing dependencies');
                    await (0, common_1.exec)('npm', ['install', '@nestjs/axios', '@nestjs/schedule']);
                    await (0, common_1.exec)('npm', ['install', '-D', '@types/cron']);
                    core_1.ux.action.stop('Completed.');
                    const project = code_writer_1.CommonDriver.createProject(['tsconfig.json']);
                    // app.module.ts file
                    const appModuleSourceFile = code_writer_1.CommonDriver.createSourceFile(project, ['src', 'app.module.ts']);
                    const appModuleClassDecoratorArguments = code_writer_1.DecoratorDriver.getClassDecoratorArguments(appModuleSourceFile, 'AppModule', 'Module');
                    _cliter_1.Installer.declareBackPackageModule(appModuleSourceFile, 'auditing', ['AuditingModule']);
                    // add ScheduleModule
                    if (!code_writer_1.ImportDriver.hasImportDeclarations(appModuleSourceFile, 'ScheduleModule')) {
                        code_writer_1.ImportDriver.createImportItems(appModuleSourceFile, '@nestjs/schedule', ['ScheduleModule']);
                        const importsArray = code_writer_1.ObjectDriver.getInitializerProperty(appModuleClassDecoratorArguments, 'imports');
                        importsArray.addElement('ScheduleModule.forRoot()', { useNewLines: true });
                    }
                    appModuleSourceFile.saveSync();
                    // shared.module.ts file
                    const sharedModuleSourceFile = code_writer_1.CommonDriver.createSourceFile(project, ['src', '@aurora', 'shared.module.ts']);
                    const classDecoratorArguments = code_writer_1.DecoratorDriver.getClassDecoratorArguments(sharedModuleSourceFile, 'SharedModule', 'Module');
                    if (!code_writer_1.ImportDriver.hasImportDeclarations(sharedModuleSourceFile, 'HttpModule')) {
                        code_writer_1.ImportDriver.createImportItems(sharedModuleSourceFile, '@nestjs/axios', ['HttpModule']);
                        const importsArray = code_writer_1.ObjectDriver.getInitializerProperty(classDecoratorArguments, 'imports');
                        importsArray.addElement('HttpModule', { useNewLines: true });
                    }
                    if (!code_writer_1.ImportDriver.hasImportDeclarations(sharedModuleSourceFile, 'AuditingAxiosInterceptorService')) {
                        code_writer_1.ImportDriver.createImportItems(sharedModuleSourceFile, '@api/auditing/shared/services/auditing-axios-interceptor.service', ['AuditingAxiosInterceptorService']);
                        const providersArray = code_writer_1.ObjectDriver.getInitializerProperty(classDecoratorArguments, 'providers');
                        providersArray.addElement('AuditingAxiosInterceptorService', { useNewLines: true });
                    }
                    code_writer_1.ImportDriver.createImportItems(sharedModuleSourceFile, '@api/auditing/shared/services/auditing-runner-aurora-implementation.service', ['AuditingRunnerAuroraImplementationService']);
                    code_writer_1.DecoratorDriver.changeModuleDecoratorPropertyAdapter(sharedModuleSourceFile, 'SharedModule', 'Module', 'providers', 'AuditingRunner', 'AuditingRunnerAuroraImplementationService');
                    sharedModuleSourceFile.saveSync();
                    core_1.ux.action.start('Generating graphql types');
                    await (0, common_1.exec)('npm', ['run', 'graphql:types']);
                    core_1.ux.action.stop('Completed.');
                    break;
                }
                case 'azureAd': {
                    await _cliter_1.BackHandler.addPackage(addCommandState);
                    core_1.ux.action.start('Installing dependencies');
                    await (0, common_1.exec)('npm', ['install', '@nestjs/passport', 'passport-azure-ad']);
                    core_1.ux.action.stop('Completed.');
                    const project = code_writer_1.CommonDriver.createProject(['tsconfig.json']);
                    // app.module.ts file
                    const appModuleSourceFile = code_writer_1.CommonDriver.createSourceFile(project, ['src', 'app.module.ts']);
                    _cliter_1.Installer.declareBackPackageModule(appModuleSourceFile, 'azure-ad', ['AzureAdModule']);
                    appModuleSourceFile.saveSync();
                    // auth.decorator.ts file, change Auth decorator
                    const authDecoratorSourceFile = code_writer_1.CommonDriver.createSourceFile(project, ['src', '@aurora', 'decorators', 'auth.decorator.ts']);
                    code_writer_1.ImportDriver.createImportItems(authDecoratorSourceFile, '@api/azure-ad/azure-ad.guard', ['AzureADGuard']);
                    const callExpression = code_writer_1.CallExpressionDriver.findCallExpression(authDecoratorSourceFile, 'UseGuards');
                    if (callExpression) {
                        code_writer_1.CallExpressionDriver.removeAllArguments(callExpression);
                        code_writer_1.CallExpressionDriver.addArgument(callExpression, 'AzureADGuard');
                    }
                    authDecoratorSourceFile.saveSync();
                    break;
                }
                case 'iam': {
                    await _cliter_1.BackHandler.addPackage(addCommandState);
                    const project = code_writer_1.CommonDriver.createProject(['tsconfig.json']);
                    const appModuleSourceFile = code_writer_1.CommonDriver.createSourceFile(project, ['src', 'app.module.ts']);
                    _cliter_1.Installer.declareBackPackageModule(appModuleSourceFile, 'iam', ['IamModule']);
                    appModuleSourceFile.saveSync();
                    // change auth decorator
                    const authDecoratorSourceFile = code_writer_1.CommonDriver.createSourceFile(project, ['src', '@aurora', 'decorators', 'auth.decorator.ts']);
                    code_writer_1.ImportDriver.createImportItems(authDecoratorSourceFile, '@api/iam/shared/guards/authorization-permissions.guard', ['AuthorizationPermissionsGuard']);
                    const callExpression = code_writer_1.CallExpressionDriver.findCallExpression(authDecoratorSourceFile, 'UseGuards');
                    if (callExpression) {
                        code_writer_1.CallExpressionDriver.replaceArgument(callExpression, 'AuthorizationDisabledAdapterGuard', 'AuthorizationPermissionsGuard');
                    }
                    authDecoratorSourceFile.saveSync();
                    core_1.ux.action.start('Generating graphql types');
                    await (0, common_1.exec)('npm', ['run', 'graphql:types']);
                    core_1.ux.action.stop('Completed.');
                    break;
                }
                case 'oAuth': {
                    await _cliter_1.BackHandler.addPackage(addCommandState);
                    core_1.ux.action.start('Installing dependencies');
                    await (0, common_1.exec)('npm', ['install', '@nestjs/jwt', '@nestjs/passport', 'passport-jwt']);
                    await (0, common_1.exec)('npm', ['install', '-D', '@types/passport-jwt']);
                    core_1.ux.action.stop('Completed.');
                    const project = code_writer_1.CommonDriver.createProject(['tsconfig.json']);
                    const appModuleSourceFile = code_writer_1.CommonDriver.createSourceFile(project, ['src', 'app.module.ts']);
                    _cliter_1.Installer.declareBackPackageModule(appModuleSourceFile, 'o-auth', ['OAuthModule']);
                    appModuleSourceFile.saveSync();
                    // imports to shared module
                    const sharedModuleSourceFile = code_writer_1.CommonDriver.createSourceFile(project, ['src', '@aurora', 'shared.module.ts']);
                    if (!code_writer_1.ImportDriver.hasImportDeclarations(sharedModuleSourceFile, 'AuthJwtStrategyRegistryModule')) {
                        code_writer_1.ImportDriver.createImportItems(sharedModuleSourceFile, '@app/o-auth/shared/modules/auth-jwt-strategy-registry.module', ['AuthJwtStrategyRegistryModule']);
                        code_writer_1.ImportDriver.createImportItems(sharedModuleSourceFile, '@app/o-auth/shared/jwt-config', ['jwtConfig']);
                        const classDecoratorArguments = code_writer_1.DecoratorDriver.getClassDecoratorArguments(sharedModuleSourceFile, 'SharedModule', 'Module');
                        const importsArray = code_writer_1.ObjectDriver.getInitializerProperty(classDecoratorArguments, 'imports');
                        importsArray.addElement('AuthJwtStrategyRegistryModule.forRoot(jwtConfig)', { useNewLines: true });
                        const exportsArray = code_writer_1.ObjectDriver.getInitializerProperty(classDecoratorArguments, 'exports');
                        exportsArray.addElement('AuthJwtStrategyRegistryModule', { useNewLines: true });
                    }
                    sharedModuleSourceFile.saveSync();
                    // change Auth decorator
                    const authDecoratorSourceFile = code_writer_1.CommonDriver.createSourceFile(project, ['src', '@aurora', 'decorators', 'auth.decorator.ts']);
                    code_writer_1.ImportDriver.createImportItems(authDecoratorSourceFile, '@api/o-auth/shared/guards/authentication-jwt.guard', ['AuthenticationJwtGuard']);
                    const callExpression = code_writer_1.CallExpressionDriver.findCallExpression(authDecoratorSourceFile, 'UseGuards');
                    if (callExpression) {
                        code_writer_1.CallExpressionDriver.replaceArgument(callExpression, 'AuthenticationDisabledAdapterGuard', 'AuthenticationJwtGuard');
                    }
                    authDecoratorSourceFile.saveSync();
                    core_1.ux.action.start('Generating graphql types');
                    await (0, common_1.exec)('npm', ['run', 'graphql:types']);
                    core_1.ux.action.stop('Completed.');
                    break;
                }
            }
        }
        if (args.firstArg === _cliter_1.Scope.FRONT) {
            switch (packageName) {
                case 'auditing': {
                    await _cliter_1.FrontHandler.addPackage(addCommandState);
                    const project = code_writer_1.CommonDriver.createProject(['tsconfig.json']);
                    const navigationSourceFile = code_writer_1.CommonDriver.createSourceFile(project, ['src', 'app', 'modules', 'admin', 'admin.navigation.ts']);
                    _cliter_1.Installer.declareFrontNavigationMenu(navigationSourceFile, 'auditing', 'auditingNavigation');
                    navigationSourceFile.saveSync();
                    const routingSourceFile = code_writer_1.CommonDriver.createSourceFile(project, ['src', 'app', 'app.routing.ts']);
                    _cliter_1.Installer.declareFrontRouting(routingSourceFile, 'auditing');
                    routingSourceFile.saveSync();
                    break;
                }
                case 'azureAd': {
                    core_1.ux.action.start('Installing dependencies');
                    await (0, common_1.exec)('npm', ['install', '@azure/msal-angular', '@azure/msal-browser']);
                    core_1.ux.action.stop('Completed.');
                    await _cliter_1.FrontHandler.addPackage(addCommandState);
                    const project = code_writer_1.CommonDriver.createProject(['tsconfig.json']);
                    // app.module.ts
                    const appModuleSourceFile = code_writer_1.CommonDriver.createSourceFile(project, ['src', 'app', 'app.module.ts']);
                    // import AzureAdModule
                    code_writer_1.ImportDriver.createImportItems(appModuleSourceFile, './modules/azure-ad/azure-ad.module', ['AzureAdModule']);
                    code_writer_1.DecoratorDriver.addModuleDecoratorProperty(appModuleSourceFile, 'AppModule', 'NgModule', 'imports', 'AzureAdModule,');
                    // implement MsalGuard adapter
                    code_writer_1.ImportDriver.createImportItems(appModuleSourceFile, '@azure/msal-angular', ['MsalGuard']);
                    code_writer_1.DecoratorDriver.addModuleDecoratorProperty(appModuleSourceFile, 'AppModule', 'NgModule', 'providers', `
{
    provide    : AuthGuard,
    useExisting: MsalGuard,
},`);
                    // implement AuthenticationAzureAdAdapterService adapter
                    code_writer_1.ImportDriver.createImportItems(appModuleSourceFile, './modules/azure-ad/authentication-azure-ad-adapter.service', ['AuthenticationAzureAdAdapterService']);
                    code_writer_1.DecoratorDriver.changeModuleDecoratorPropertyAdapter(appModuleSourceFile, 'AppModule', 'NgModule', 'providers', 'AuthenticationService', 'AuthenticationAzureAdAdapterService');
                    // implement AuthorizationAzureAdAdapterService adapter
                    code_writer_1.ImportDriver.createImportItems(appModuleSourceFile, './modules/azure-ad/authorization-azure-ad-adapter.service', ['AuthorizationAzureAdAdapterService']);
                    code_writer_1.DecoratorDriver.addModuleDecoratorProperty(appModuleSourceFile, 'AppModule', 'NgModule', 'providers', `
{
    provide    : AuthorizationService,
    useExisting: AuthorizationAzureAdAdapterService,
},`);
                    // implement IamAzureAdAdapterService adapter
                    code_writer_1.ImportDriver.createImportItems(appModuleSourceFile, './modules/azure-ad/iam-azure-ad-adapter.service', ['IamAzureAdAdapterService']);
                    code_writer_1.DecoratorDriver.changeModuleDecoratorPropertyAdapter(appModuleSourceFile, 'AppModule', 'NgModule', 'providers', 'IamService', 'IamAzureAdAdapterService');
                    appModuleSourceFile.organizeImports();
                    appModuleSourceFile.saveSync();
                    // implement environments azure ad variables
                    const environmentFile = code_writer_1.CommonDriver.createSourceFile(project, ['src', 'environments', 'environment.ts']);
                    const environmentVariable = code_writer_1.VariableDriver.getVariable(environmentFile, 'environment');
                    const environmentObject = environmentVariable === null || environmentVariable === void 0 ? void 0 : environmentVariable.getInitializerIfKindOrThrow(ts_morph_1.SyntaxKind.ObjectLiteralExpression);
                    environmentObject === null || environmentObject === void 0 ? void 0 : environmentObject.addPropertyAssignment({
                        name: 'azureAd',
                        initializer: ts_morph_1.Writers.object({
                            tenant: '\'\'',
                            authority: '\'\'',
                            clientId: '\'\'',
                            redirectUri: '\'\'',
                            scopes: '[]',
                        }),
                    });
                    environmentFile.saveSync();
                    // implement environments azure ad variables
                    const environmentProdFile = code_writer_1.CommonDriver.createSourceFile(project, ['src', 'environments', 'environment.prod.ts']);
                    const environmentProdVariable = code_writer_1.VariableDriver.getVariable(environmentProdFile, 'environment');
                    const environmentProdObject = environmentProdVariable === null || environmentProdVariable === void 0 ? void 0 : environmentProdVariable.getInitializerIfKindOrThrow(ts_morph_1.SyntaxKind.ObjectLiteralExpression);
                    environmentProdObject === null || environmentProdObject === void 0 ? void 0 : environmentProdObject.addPropertyAssignment({
                        name: 'azureAd',
                        initializer: ts_morph_1.Writers.object({
                            tenant: '\'\'',
                            authority: '\'\'',
                            clientId: '\'\'',
                            redirectUri: '\'\'',
                            scopes: '[]',
                        }),
                    });
                    environmentProdFile.saveSync();
                    // implement environments azure ad variables
                    const environmentLocalFile = code_writer_1.CommonDriver.createSourceFile(project, ['src', 'environments', 'environment.local.ts']);
                    const environmentLocalVariable = code_writer_1.VariableDriver.getVariable(environmentLocalFile, 'environment');
                    const environmentLocalObject = environmentLocalVariable === null || environmentLocalVariable === void 0 ? void 0 : environmentLocalVariable.getInitializerIfKindOrThrow(ts_morph_1.SyntaxKind.ObjectLiteralExpression);
                    environmentLocalObject === null || environmentLocalObject === void 0 ? void 0 : environmentLocalObject.addPropertyAssignment({
                        name: 'azureAd',
                        initializer: ts_morph_1.Writers.object({
                            tenant: '\'\'',
                            authority: '\'\'',
                            clientId: '\'\'',
                            redirectUri: '\'\'',
                            scopes: '[]',
                        }),
                    });
                    environmentLocalFile.saveSync();
                    // implement environments azure ad variables
                    const environmentDevFile = code_writer_1.CommonDriver.createSourceFile(project, ['src', 'environments', 'environment.dev.ts']);
                    const environmentDevVariable = code_writer_1.VariableDriver.getVariable(environmentDevFile, 'environment');
                    const environmentDevObject = environmentDevVariable === null || environmentDevVariable === void 0 ? void 0 : environmentDevVariable.getInitializerIfKindOrThrow(ts_morph_1.SyntaxKind.ObjectLiteralExpression);
                    environmentDevObject === null || environmentDevObject === void 0 ? void 0 : environmentDevObject.addPropertyAssignment({
                        name: 'azureAd',
                        initializer: ts_morph_1.Writers.object({
                            tenant: '\'\'',
                            authority: '\'\'',
                            clientId: '\'\'',
                            redirectUri: '\'\'',
                            scopes: '[]',
                        }),
                    });
                    environmentDevFile.saveSync();
                    break;
                }
                case 'iam': {
                    await _cliter_1.FrontHandler.addPackage(addCommandState);
                    const project = code_writer_1.CommonDriver.createProject(['tsconfig.json']);
                    const navigationSourceFile = code_writer_1.CommonDriver.createSourceFile(project, ['src', 'app', 'modules', 'admin', 'admin.navigation.ts']);
                    _cliter_1.Installer.declareFrontNavigationMenu(navigationSourceFile, 'iam', 'iamNavigation');
                    navigationSourceFile.saveSync();
                    const routingSourceFile = code_writer_1.CommonDriver.createSourceFile(project, ['src', 'app', 'app.routing.ts']);
                    _cliter_1.Installer.declareFrontRouting(routingSourceFile, 'iam');
                    routingSourceFile.saveSync();
                    // add custom imports
                    const appModuleSourceFile = code_writer_1.CommonDriver.createSourceFile(project, ['src', 'app', 'app.module.ts']);
                    if (!code_writer_1.ImportDriver.hasImportDeclarations(appModuleSourceFile, 'UserMetaStorageIamAdapterService')) {
                        code_writer_1.ImportDriver.createImportItems(appModuleSourceFile, './modules/admin/apps/iam/user-meta/user-meta-storage-iam-adapter.service', ['UserMetaStorageIamAdapterService']);
                    }
                    code_writer_1.DecoratorDriver.changeModuleDecoratorPropertyAdapter(appModuleSourceFile, 'AppModule', 'NgModule', 'providers', 'UserMetaStorageService', 'UserMetaStorageIamAdapterService');
                    code_writer_1.DecoratorDriver.changeModuleDecoratorPropertyAdapter(appModuleSourceFile, 'AppModule', 'NgModule', 'providers', 'IamService', 'IamAuroraAdapterService');
                    appModuleSourceFile.saveSync();
                    break;
                }
                case 'oAuth': {
                    await _cliter_1.FrontHandler.addPackage(addCommandState);
                    const project = code_writer_1.CommonDriver.createProject(['tsconfig.json']);
                    const navigationSourceFile = code_writer_1.CommonDriver.createSourceFile(project, ['src', 'app', 'modules', 'admin', 'admin.navigation.ts']);
                    _cliter_1.Installer.declareFrontNavigationMenu(navigationSourceFile, 'oAuth', 'oAuthNavigation');
                    navigationSourceFile.saveSync();
                    const routingSourceFile = code_writer_1.CommonDriver.createSourceFile(project, ['src', 'app', 'app.routing.ts']);
                    _cliter_1.Installer.declareFrontRouting(routingSourceFile, 'oAuth');
                    routingSourceFile.saveSync();
                    // app.module.ts
                    const appModuleSourceFile = code_writer_1.CommonDriver.createSourceFile(project, ['src', 'app', 'app.module.ts']);
                    code_writer_1.DecoratorDriver.changeModuleDecoratorPropertyAdapter(appModuleSourceFile, 'AppModule', 'NgModule', 'providers', 'AuthenticationService', 'AuthenticationAuroraAdapterService');
                    code_writer_1.DecoratorDriver.removeDecoratorAdapter(appModuleSourceFile, 'AppModule', 'NgModule', 'providers', 'AuthGuard');
                    appModuleSourceFile.saveSync();
                    break;
                }
                case 'environments': {
                    const project = code_writer_1.CommonDriver.createProject(['tsconfig.json']);
                    const appModuleSourceFile = code_writer_1.CommonDriver.createSourceFile(project, ['src', 'app', 'app.module.ts']);
                    code_writer_1.DecoratorDriver.removeDecoratorAdapter(appModuleSourceFile, 'AppModule', 'NgModule', 'providers', 'EnvironmentsInformationService');
                    appModuleSourceFile.saveSync();
                }
            }
        }
    }
}
exports.Add = Add;
Add.description = 'Add a aurora package';
Add.flags = {
    help: core_1.Flags.help({ char: 'h' }),
    force: core_1.Flags.boolean({
        char: 'f',
        description: 'Overwrite existing files.',
    }),
};
Add.args = {
    firstArg: core_1.Args.string({
        name: 'scope',
        required: true,
        description: 'Scope where our command will act.',
        options: [
            _cliter_1.Scope.BACK,
            _cliter_1.Scope.FRONT,
        ],
    }),
};
Add.examples = [
    '$ aurora add back auditing',
    '$ aurora add back auditing -f',
    '$ aurora --help',
];
