"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.addPackageToPkgJson = exports.getPropertyFromWorkspace = exports.addDependencies = exports.logSuccess = exports.overwriteJsonFile = exports.getConfigFile = exports.DEPENDENCIES_MAP = exports.PackageTarget = void 0;
const schematics_1 = require("@angular-devkit/schematics");
const config_1 = require("@schematics/angular/utility/config");
var PackageTarget;
(function (PackageTarget) {
    PackageTarget["DEV"] = "devDependencies";
    PackageTarget["REGULAR"] = "dependencies";
    PackageTarget["NONE"] = "none";
})(PackageTarget = exports.PackageTarget || (exports.PackageTarget = {}));
const schematicsPackage = '@igniteui/angular-schematics';
/**
 * Dependencies are explicitly defined here, so we avoid adding
 * unnecessary packages to the consuming project's deps
 */
exports.DEPENDENCIES_MAP = [
    // dependencies
    { name: 'hammerjs', target: PackageTarget.REGULAR },
    { name: 'jszip', target: PackageTarget.REGULAR },
    { name: 'tslib', target: PackageTarget.NONE },
    { name: 'resize-observer-polyfill', target: PackageTarget.REGULAR },
    { name: '@types/hammerjs', target: PackageTarget.DEV },
    { name: 'igniteui-trial-watermark', target: PackageTarget.NONE },
    { name: 'lodash.mergewith', target: PackageTarget.NONE },
    { name: 'uuid', target: PackageTarget.NONE },
    { name: 'web-animations-js', target: PackageTarget.REGULAR },
    { name: '@igniteui/material-icons-extended', target: PackageTarget.REGULAR },
    // peerDependencies
    { name: '@angular/forms', target: PackageTarget.NONE },
    { name: '@angular/common', target: PackageTarget.NONE },
    { name: '@angular/core', target: PackageTarget.NONE },
    { name: '@angular/animations', target: PackageTarget.NONE },
    // igxDevDependencies
    { name: '@igniteui/angular-schematics', target: PackageTarget.DEV }
];
const logIncludingDependency = (context, pkg, version) => context.logger.info(`Including ${pkg} - Version: ${version}`);
const getTargetedProjectOptions = (project, target) => {
    if (project.targets &&
        project.targets[target] &&
        project.targets[target].options) {
        return project.targets[target].options;
    }
    if (project.architect &&
        project.architect[target] &&
        project.architect[target].options) {
        return project.architect[target].options;
    }
    throw new schematics_1.SchematicsException(`Cannot determine the project's configuration for: ${target}`);
};
exports.getConfigFile = (project, option, configSection = 'build') => {
    const options = getTargetedProjectOptions(project, configSection);
    if (!options) {
        throw new schematics_1.SchematicsException(`Could not find matching ${configSection} section` +
            `inside of the workspace config ${project.sourceRoot} `);
    }
    if (!options[option]) {
        throw new schematics_1.SchematicsException(`Could not find the project ${option} file inside of the ` +
            `workspace config ${project.sourceRoot}`);
    }
    return options[option];
};
exports.overwriteJsonFile = (tree, targetFile, data) => tree.overwrite(targetFile, JSON.stringify(data, null, 2) + '\n');
exports.logSuccess = (options) => (tree, context) => {
    context.logger.info('');
    context.logger.warn('Ignite UI for Angular installed');
    context.logger.info('Learn more: https://www.infragistics.com/products/ignite-ui-angular');
    context.logger.info('');
};
exports.addDependencies = (options) => (tree, context) => {
    const pkgJson = require('../../package.json');
    includeDependencies(pkgJson, context, tree);
    // Add web-animations-js to dependencies
    Object.keys(pkgJson.peerDependencies).forEach(pkg => {
        if (pkg.includes('web-animations')) {
            const version = pkgJson.peerDependencies[pkg];
            exports.addPackageToPkgJson(tree, pkg, version, PackageTarget.REGULAR);
            logIncludingDependency(context, pkg, version);
            return;
        }
    });
    exports.addPackageToPkgJson(tree, schematicsPackage, pkgJson.igxDevDependencies[schematicsPackage], PackageTarget.DEV);
    return tree;
};
/**
 * Recursively search for the first property that matches targetProp within a json file.
 */
exports.getPropertyFromWorkspace = (targetProp, workspace, curKey = '') => {
    if (workspace.hasOwnProperty(targetProp)) {
        return { key: targetProp, value: workspace[targetProp] };
    }
    const workspaceKeys = Object.keys(workspace);
    for (const key of workspaceKeys) {
        // If the target property is an array, return its key and its contents.
        if (Array.isArray(workspace[key])) {
            return {
                key: curKey,
                value: workspace[key]
            };
        }
        else if (workspace[key] instanceof Object) {
            // If the target property is an object, go one level in.
            if (workspace.hasOwnProperty(key)) {
                const newValue = exports.getPropertyFromWorkspace(targetProp, workspace[key], key);
                if (newValue) {
                    return newValue;
                }
            }
        }
    }
    return null;
};
const addHammerToConfig = (project, tree, config) => {
    const projectOptions = getTargetedProjectOptions(project, config);
    const tsPath = exports.getConfigFile(project, 'main', config);
    const hammerImport = 'import \'hammerjs\';\n';
    const tsContent = tree.read(tsPath).toString();
    // if there are no elements in the architect[config]options.scripts array that contain hammerjs
    // and the "main" file does not contain an import with hammerjs
    if (!projectOptions.scripts.some(el => el.includes('hammerjs')) && !tsContent.includes(hammerImport)) {
        // import hammerjs in the specified by config main file
        const mainContents = hammerImport + tsContent;
        tree.overwrite(tsPath, mainContents);
    }
};
const includeDependencies = (pkgJson, context, tree) => {
    Object.keys(pkgJson.dependencies).forEach(pkg => {
        const version = pkgJson.dependencies[pkg];
        const entry = exports.DEPENDENCIES_MAP.find(e => e.name === pkg);
        if (!entry || entry.target === PackageTarget.NONE) {
            return;
        }
        switch (pkg) {
            case 'hammerjs':
                logIncludingDependency(context, pkg, version);
                exports.addPackageToPkgJson(tree, pkg, version, entry.target);
                const workspace = config_1.getWorkspace(tree);
                const project = workspace.projects[workspace.defaultProject];
                addHammerToConfig(project, tree, 'build');
                addHammerToConfig(project, tree, 'test');
                break;
            default:
                logIncludingDependency(context, pkg, version);
                exports.addPackageToPkgJson(tree, pkg, version, entry.target);
                break;
        }
    });
};
exports.addPackageToPkgJson = (tree, pkg, version, target) => {
    const targetFile = 'package.json';
    if (tree.exists(targetFile)) {
        const sourceText = tree.read(targetFile).toString();
        const json = JSON.parse(sourceText);
        if (!json[target]) {
            json[target] = {};
        }
        if (!json.dependencies[pkg]) {
            json[target][pkg] = version;
            json[target] =
                Object.keys(json[target])
                    .sort()
                    .reduce((result, key) => (result[key] = json[target][key]) && result, {});
            tree.overwrite(targetFile, JSON.stringify(json, null, 2) + '\n');
        }
        return true;
    }
    return false;
};
