"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = default_1;
exports.addImportOnly = addImportOnly;
exports.addProviderToAppModule = addProviderToAppModule;
exports.addProviderToModuleProvider = addProviderToModuleProvider;
exports.updateAppConfigFile = updateAppConfigFile;
const schematics_1 = require("@angular-devkit/schematics");
const ng_ast_utils_1 = require("@schematics/angular/utility/ng-ast-utils");
const module_1 = require("@po-ui/ng-schematics/module");
const project_1 = require("@po-ui/ng-schematics/project");
const ast_utils_1 = require("@schematics/angular/utility/ast-utils");
/** PO Module name that will insert in app root module */
const poModuleName = 'PoModule';
const poModuleSourcePath = '@po-ui/ng-components';
/** HttpClient Module name that will insert in app root module */
const httpProvideHttpClientName = 'provideHttpClient';
const httpWithInterceptorsFromDiName = 'withInterceptorsFromDi';
const httpClientModuleSourcePath = '@angular/common/http';
/**
 * Scaffolds the basics of a Angular Material application, this includes:
 *  - Add PO Module to app root module
 *  - Adds themes to styles
 *  - Run sidemenu schematic
 */
function default_1(options) {
    return (0, schematics_1.chain)([
        (0, module_1.addModuleImportToRootModule)(options, poModuleName, poModuleSourcePath),
        addImportOnly(options, [httpProvideHttpClientName, httpWithInterceptorsFromDiName], httpClientModuleSourcePath),
        addProviderToAppModule(options, 'provideHttpClient(withInterceptorsFromDi())'),
        addThemeToAppStyles(options),
        addPolyfillsZoneJS(options),
        updateAppConfigFileRule(options),
        configureSideMenu(options)
    ]);
}
//insere um import no módulo sem adicionar na lista de importação
function addImportOnly(options, moduleNames, importPath) {
    return (host) => {
        var _a;
        const workspace = (_a = (0, project_1.getWorkspaceConfigGracefully)(host)) !== null && _a !== void 0 ? _a : {};
        const project = (0, project_1.getProjectFromWorkspace)(workspace, options.project);
        const browserEntryPoint = (0, project_1.getProjectMainFile)(project);
        if ((0, ng_ast_utils_1.isStandaloneApp)(host, browserEntryPoint)) {
            return host;
        }
        const modulePath = (0, ng_ast_utils_1.getAppModulePath)(host, browserEntryPoint);
        let importStatement;
        if (Array.isArray(moduleNames)) {
            const names = moduleNames.join(', ');
            importStatement = `import { ${names} } from '${importPath}';\n`;
        }
        else {
            importStatement = `import { ${moduleNames} } from '${importPath}';\n`;
        }
        const recorder = host.beginUpdate(modulePath);
        recorder.insertLeft(0, importStatement);
        host.commitUpdate(recorder);
        return host;
    };
}
/** Add PO theme to project styles */
function addThemeToAppStyles(options) {
    return function (tree) {
        var _a;
        const workspace = (_a = (0, project_1.getWorkspaceConfigGracefully)(tree)) !== null && _a !== void 0 ? _a : {};
        const project = (0, project_1.getProjectFromWorkspace)(workspace, options.project);
        // Path needs to be always relative to the `package.json` or workspace root.
        const themePath = './node_modules/@po-ui/style/css/po-theme-default.min.css';
        addThemeStyleToTarget(project, 'build', tree, themePath, workspace);
        return tree;
    };
}
/** Adds a theming style entry to the given project target options. */
function addThemeStyleToTarget(project, targetName, host, assetPath, workspace) {
    const targetOptions = (0, project_1.getProjectTargetOptions)(project, targetName);
    if (!targetOptions.styles) {
        targetOptions.styles = [assetPath];
    }
    else {
        const existingStyles = targetOptions.styles.map((s) => (typeof s === 'string' ? s : s.input));
        for (const [, stylePath] of existingStyles.entries()) {
            if (stylePath === assetPath) {
                return;
            }
        }
        targetOptions.styles.unshift(assetPath);
    }
    host.overwrite('angular.json', JSON.stringify(workspace, null, 2));
}
function configureSideMenu(options) {
    return options.configSideMenu ? (0, schematics_1.schematic)('sidemenu', Object.assign({}, options)) : (0, schematics_1.noop)();
}
function updateAppConfigFileRule(options) {
    return (tree) => {
        var _a, _b;
        const workspace = (_a = (0, project_1.getWorkspaceConfigGracefully)(tree)) !== null && _a !== void 0 ? _a : {};
        const project = (0, project_1.getProjectFromWorkspace)(workspace, options.project);
        const browserEntryPoint = (0, project_1.getProjectMainFile)(project);
        if (!(0, ng_ast_utils_1.isStandaloneApp)(tree, browserEntryPoint)) {
            return tree;
        }
        const content = ((_b = tree.read('src/app/app.config.ts')) === null || _b === void 0 ? void 0 : _b.toString('utf-8')) || '';
        const conteudoModificado = updateAppConfigFile(content);
        tree.overwrite('src/app/app.config.ts', conteudoModificado);
        return tree;
    };
}
function addProviderToAppModule(options, provider) {
    return (host) => {
        var _a;
        const workspace = (_a = (0, project_1.getWorkspaceConfigGracefully)(host)) !== null && _a !== void 0 ? _a : {};
        const project = (0, project_1.getProjectFromWorkspace)(workspace, options.project);
        const browserEntryPoint = (0, project_1.getProjectMainFile)(project);
        if ((0, ng_ast_utils_1.isStandaloneApp)(host, browserEntryPoint)) {
            return host;
        }
        const appModulePath = (0, ng_ast_utils_1.getAppModulePath)(host, browserEntryPoint);
        addProviderToModuleProvider(host, appModulePath, provider);
        return host;
    };
}
// para inserir variáveis no provider
function addProviderToModuleProvider(tree, modulePath, provider) {
    const moduleSource = (0, module_1.getSourceFile)(tree, modulePath);
    const changes = (0, ast_utils_1.addProviderToModule)(moduleSource, modulePath, `
    ${provider}`, 
    // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
    null);
    return insertChanges(tree, changes, modulePath);
}
/** Inserts the specified changes into the module file. */
function insertChanges(tree, changes, modulePath) {
    const recorder = tree.beginUpdate(modulePath);
    changes.forEach(change => {
        if (change) {
            recorder.insertLeft(change.pos, change.toAdd);
        }
    });
    tree.commitUpdate(recorder);
}
function updateAppConfigFile(content) {
    const importBlock = `
import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';

import { PoHttpRequestModule } from '@po-ui/ng-components';
`;
    const providersBlock = `
  providers: [
    provideBrowserGlobalErrorListeners(),
    provideRouter(routes),
    importProvidersFrom([PoHttpRequestModule]),
    provideZoneChangeDetection({ eventCoalescing: true }),
    provideHttpClient(withInterceptorsFromDi())
  ],`;
    const regexImport = /import {[^}]+} from '@angular\/core';/;
    const regexProviders = /providers: \[[^\]]+\]/;
    // Remove imports e providers existentes
    let modifiedContent = content.replace(regexImport, '').replace(regexProviders, '');
    // Adiciona os novos imports e providers
    modifiedContent = modifiedContent.replace(/export const appConfig: ApplicationConfig = {/, `import { ApplicationConfig, importProvidersFrom, provideBrowserGlobalErrorListeners, provideZoneChangeDetection } from '@angular/core';${importBlock}
export const appConfig: ApplicationConfig = {${providersBlock}`);
    return modifiedContent.trim();
}
// Adiciona zone.js ao polyfills, caso não exista
function addPolyfillsZoneJS(options) {
    return function (tree) {
        var _a;
        const workspace = (_a = (0, project_1.getWorkspaceConfigGracefully)(tree)) !== null && _a !== void 0 ? _a : {};
        const project = (0, project_1.getProjectFromWorkspace)(workspace, options.project);
        const targetOptions = (0, project_1.getProjectTargetOptions)(project, 'build');
        const zoneJs = 'zone.js';
        if (!targetOptions.polyfills) {
            targetOptions.polyfills = [zoneJs];
        }
        else {
            const existingZoneJs = targetOptions.polyfills.map((s) => (typeof s === 'string' ? s : s.input));
            for (const [, polyfillsName] of existingZoneJs.entries()) {
                if (polyfillsName === zoneJs) {
                    return tree;
                }
            }
            targetOptions.polyfills.unshift(zoneJs);
        }
        tree.overwrite('angular.json', JSON.stringify(workspace, null, 2));
        return tree;
    };
}
//# sourceMappingURL=setup-project.js.map