"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const testing_1 = require("@angular-devkit/schematics/testing");
const schematics_1 = require("@angular-devkit/schematics");
const core_1 = require("@angular-devkit/core");
const test_1 = require("@schematics/angular/utility/test");
const defaultProjectSettings = {
    projectName: 'my-project',
    sourceDirectory: 'src',
    importPrefix: '@src',
    webExtension: '',
    nsExtension: '.tns',
    shared: true,
};
exports.isInModuleMetadata = (moduleName, property, value, inArray) => exports.isInDecoratorMetadata(moduleName, property, value, 'NgModule', inArray);
exports.isInComponentMetadata = (componentName, property, value, inArray) => exports.isInDecoratorMetadata(componentName, property, value, 'Component', inArray);
exports.isInDecoratorMetadata = (moduleName, property, value, decoratorName, inArray) => new RegExp(`@${decoratorName}\\(\\{([^}]*)` +
    objectContaining(property, value, inArray) +
    '[^}]*\\}\\)' +
    '\\s*' +
    `(export )?class ${moduleName}`);
const objectContaining = (property, value, inArray) => inArray ?
    keyValueInArray(property, value) :
    keyValueString(property, value);
const keyValueInArray = (property, value) => `${property}: \\[` +
    nonLastValueInArrayMatcher +
    `${value},?` +
    nonLastValueInArrayMatcher +
    lastValueInArrayMatcher +
    `\\s*]`;
const nonLastValueInArrayMatcher = `(\\s*|(\\s*(\\w+,)*)\\s*)*`;
const lastValueInArrayMatcher = `(\\s*|(\\s*(\\w+)*)\\s*)?`;
const keyValueString = (property, value) => `${property}: ${value}`;
function setupTestTree(files) {
    const memoryFs = new core_1.virtualFs.SimpleMemoryHost();
    files.forEach(file => {
        const path = file.path;
        // The write method of memoryFs expects an ArrayBuffer.
        // However, when the read method is used to fetch the file from the FS
        // the returned value is not converted properly to string.
        // This is why we're using node Buffer to write the file in the memory FS.
        // const content = stringToArrayBuffer(file.content);
        const content = Buffer.from(file.content);
        memoryFs.write(path, content).subscribe();
    });
    const host = new schematics_1.HostTree(memoryFs);
    const tree = new testing_1.UnitTestTree(host);
    return tree;
}
function createEmptyNsOnlyProject(projectName, nsExtension = '') {
    const setup = Object.assign({}, defaultProjectSettings, { projectName, nsExtension });
    const additionalFiles = [
        getNsPackageJson(setup),
        getNsEntryPoint(setup)
    ];
    return createTestProject(setup, additionalFiles);
}
exports.createEmptyNsOnlyProject = createEmptyNsOnlyProject;
function createEmptySharedProject(projectName, webExtension = '', nsExtension = '.tns') {
    const setup = Object.assign({}, defaultProjectSettings, { projectName, webExtension, nsExtension });
    const additionalFiles = [
        getNsConfig(setup),
        getAppModule(setup.webExtension),
    ];
    return createTestProject(setup, additionalFiles);
}
exports.createEmptySharedProject = createEmptySharedProject;
function createTestProject(setup, additionalFiles = []) {
    setup = Object.assign(defaultProjectSettings, setup);
    const files = [];
    files.push(getBaseTypescriptConfig(setup));
    const { path: webConfigPath, content: webConfigContent } = getWebTypescriptConfig(setup);
    files.push({ path: webConfigPath, content: webConfigContent });
    files.push(getAngularProjectConfig(webConfigPath, setup));
    files.push(getPackageJson(setup));
    files.push(getAppModule(setup.nsExtension));
    files.push(...additionalFiles);
    const virtualTree = setupTestTree(files);
    return virtualTree;
}
exports.createTestProject = createTestProject;
function getPackageJson(setup) {
    return {
        path: '/package.json',
        content: JSON.stringify({
            nativescript: { id: setup.projectName },
            dependencies: {
                '@angular/core': '^6.1.0'
            },
            devDependencies: {
                '@angular/cli': '^6.2.0'
            },
        })
    };
}
function getNsConfig(setup) {
    return {
        path: '/nsconfig.json',
        content: JSON.stringify({
            'appResourcesPath': 'App_Resources',
            'appPath': setup.sourceDirectory,
            'nsext': setup.nsExtension,
            'webext': setup.webExtension,
            'shared': true,
            'useLegacyWorkflow': false
        })
    };
}
function getBaseTypescriptConfig({ sourceDirectory, importPrefix }) {
    const baseConfigPath = 'tsconfig.json';
    const baseConfigObject = {
        compileOnSave: false,
        compilerOptions: {
            outDir: './dist/out-tsc',
            declaration: false,
            moduleResolution: 'node',
            emitDecoratorMetadata: true,
            experimentalDecorators: true,
            target: 'es5',
            typeRoots: [
                'node_modules/@types'
            ],
            lib: [
                'es2017',
                'dom',
                'es6',
                'es2015.iterable'
            ],
            baseUrl: '.',
            paths: {
                '~/*': [
                    `${sourceDirectory}/`
                ]
            }
        }
    };
    const baseImportRemapKey = `${importPrefix}/*`;
    const baseImportMap = [
        `${sourceDirectory}/*.android.ts`,
        `${sourceDirectory}/*.ios.ts`,
        `${sourceDirectory}/*.tns.ts`,
        `${sourceDirectory}/*.web.ts`,
        `${sourceDirectory}/`
    ];
    baseConfigObject.compilerOptions.paths[baseImportRemapKey] = baseImportMap;
    const baseConfigContent = JSON.stringify(baseConfigObject);
    return { path: baseConfigPath, content: baseConfigContent };
}
function getWebTypescriptConfig({ sourceDirectory, importPrefix }) {
    const webConfigPath = 'tsconfig.app.json';
    const webImportRemapKey = `${importPrefix}/*`;
    const webImportMap = [
        `${sourceDirectory}/*.web`,
        `${sourceDirectory}/`
    ];
    const webConfigObject = {
        'extends': './tsconfig.json',
        compilerOptions: {
            outDir: './out-tsc/app',
            'module': 'es2015',
            types: [],
            paths: {}
        }
    };
    webConfigObject.compilerOptions.paths[webImportRemapKey] = webImportMap;
    const webConfigContent = JSON.stringify(webConfigObject);
    return { path: webConfigPath, content: webConfigContent };
}
function getAngularProjectConfig(webConfigPath, setup) {
    const angularJsonPath = 'angular.json';
    const architect = {
        build: {
            options: {
                tsConfig: webConfigPath
            }
        }
    };
    const angularJsonObject = {
        "$schema": './node_modules/@angular/cli/lib/config/schema.json',
        version: 1,
        defaultProject: setup.projectName,
        projects: {
            [setup.projectName]: {
                projectType: 'application',
                sourceRoot: setup.sourceDirectory,
                prefix: 'app',
                architect: setup.shared ? architect : undefined
            }
        }
    };
    const angularJsonContent = JSON.stringify(angularJsonObject);
    return { path: angularJsonPath, content: angularJsonContent };
}
function getAppModule(extension) {
    const path = `/src/app/app.module${extension}.ts`;
    // Ugly ... but we need a tree to call createAppModule()
    const tree = new testing_1.UnitTestTree(new schematics_1.HostTree(new core_1.virtualFs.SimpleMemoryHost()));
    test_1.createAppModule(tree, path);
    const file = tree.get(path);
    return {
        path,
        content: file.content.toString()
    };
}
function getNsEntryPoint(setup) {
    return {
        path: `${setup.sourceDirectory}/main.ts`,
        content: `
      import { platformNativeScriptDynamic } from 'nativescript-angular/platform';
      import { AppModule } from './app/app.module';

      platformNativeScriptDynamic().bootstrapModule(AppModule);
    `
    };
}
function getNsPackageJson(setup) {
    return {
        path: `${setup.sourceDirectory}/package.json`,
        content: JSON.stringify({
            android: {
                v8Flags: '--expose_gc'
            },
            main: 'main.js'
        })
    };
}
//# sourceMappingURL=test-utils.js.map