"use strict";
// © 2022 SolarWinds Worldwide, LLC. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
//  of this software and associated documentation files (the "Software"), to
//  deal in the Software without restriction, including without limitation the
//  rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
//  sell copies of the Software, and to permit persons to whom the Software is
//  furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
//  all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//  THE SOFTWARE.
Object.defineProperty(exports, "__esModule", { value: true });
exports.omitUpperPeerDependencyVersion = exports.assembleDependencies = exports.installPackageJsonDependencies = exports.addStylesToAngularJson = exports.getBrowserProjectTargets = exports.updateModuleChanges = exports.readIntoSourceFile = exports.buildSelector = exports.updateJsonFile = void 0;
const tslib_1 = require("tslib");
const core_1 = require("@angular-devkit/core");
const parser_1 = require("@angular-devkit/core/src/json/parser");
const schematics_1 = require("@angular-devkit/schematics");
const tasks_1 = require("@angular-devkit/schematics/tasks");
const schematics_2 = require("@angular/cdk/schematics");
const ast_utils_1 = require("@schematics/angular/utility/ast-utils");
const change_1 = require("@schematics/angular/utility/change");
const dependencies_1 = require("@schematics/angular/utility/dependencies");
const typescript_1 = tslib_1.__importDefault(require("typescript"));
const json_utils_1 = require("./json-utils");
const project_1 = require("./project");
const project_targets_1 = require("./project-targets");
const workspace_1 = require("./workspace");
function updateJsonFile(host, context, filename, propertyChain, itemToAdd) {
    var _a, _b;
    const lastProperty = propertyChain[propertyChain.length - 1];
    try {
        const source = (_b = (_a = host.read(filename)) === null || _a === void 0 ? void 0 : _a.toString("utf-8")) !== null && _b !== void 0 ? _b : "";
        const sourceAstObj = (0, parser_1.parseJsonAst)(source, parser_1.JsonParseMode.CommentsAllowed);
        let targetObj, parentObj;
        targetObj = sourceAstObj;
        for (let i = 0; i < propertyChain.length; i++) {
            parentObj = targetObj;
            targetObj = ((0, json_utils_1.findPropertyInAstObject)(parentObj, propertyChain[i]));
        }
        const recorder = host.beginUpdate(filename);
        const targetArray = targetObj;
        if (targetArray && Array.isArray(itemToAdd)) {
            if (targetArray.elements.every(
            //  we don't want a double not equal here
            // tslint:disable-next-line:triple-equals
            (element) => element.value != itemToAdd)) {
                const lastStyle = targetArray.elements[targetArray.elements.length - 1];
                const lastStyleIndent = lastStyle
                    ? lastStyle.start.character
                    : 0;
                (0, json_utils_1.appendValueInAstArray)(recorder, targetArray, itemToAdd[0], lastStyleIndent);
            }
            else {
                context.logger.info(`️ ${filename} already contains ${lastProperty}`);
            }
        }
        else {
            if (parentObj === null || parentObj === void 0 ? void 0 : parentObj.properties.every(
            // we don't want a double not equal here
            // tslint:disable-next-line:triple-equals
            (property) => property.key.value != lastProperty)) {
                const lastItemIndent = parentObj.properties[0]
                    ? parentObj.properties[0].start.character
                    : 0;
                (0, json_utils_1.insertPropertyInAstObjectInOrder)(recorder, parentObj, lastProperty, itemToAdd, lastItemIndent);
            }
            else {
                context.logger.info(`️ ${filename} already contains ${lastProperty}`);
            }
        }
        host.commitUpdate(recorder);
    }
    catch (ex) {
        context.logger.error(`🚫 Failed to update ${filename} with ${lastProperty}: ${ex.toString()}`);
    }
    context.logger.info(`✅️ Updated ${filename} with ${lastProperty}`);
    return host;
}
exports.updateJsonFile = updateJsonFile;
function buildSelector(options, projectPrefix) {
    let selector = core_1.strings.dasherize(options.name);
    if (options.prefix) {
        selector = `${options.prefix}-${selector}`;
    }
    else if (options.prefix === undefined && projectPrefix) {
        selector = `${projectPrefix}-${selector}`;
    }
    return selector;
}
exports.buildSelector = buildSelector;
function readIntoSourceFile(host, modulePath) {
    const text = host.read(modulePath);
    if (text === null) {
        throw new schematics_1.SchematicsException(`File ${modulePath} does not exist.`);
    }
    const sourceText = text.toString("utf-8");
    return typescript_1.default.createSourceFile(modulePath, sourceText, typescript_1.default.ScriptTarget.Latest, true);
}
exports.readIntoSourceFile = readIntoSourceFile;
function updateModuleChanges(host, options, moduleSource, modules, providers = [], declarations = []) {
    const modulePath = options.module;
    const declarationRecorder = host.beginUpdate(modulePath);
    declarations.forEach((item) => {
        const changeList = (0, ast_utils_1.addDeclarationToModule)(moduleSource, modulePath, item.item, item.path);
        changeList.forEach((change) => {
            if (change instanceof change_1.InsertChange) {
                declarationRecorder.insertLeft(change.pos, change.toAdd);
            }
        });
    });
    providers.forEach((item) => {
        const changeList = (0, ast_utils_1.addProviderToModule)(moduleSource, modulePath, item.item, item.path);
        changeList.forEach((change) => {
            if (change instanceof change_1.InsertChange) {
                declarationRecorder.insertLeft(change.pos, change.toAdd);
            }
        });
    });
    modules.forEach((item) => {
        if (!(0, ast_utils_1.isImported)(moduleSource, item.item, item.path)) {
            const moduleChanges = (0, schematics_2.addImportToModule)(moduleSource, modulePath, item.item, item.path);
            moduleChanges.forEach((change) => {
                if (change instanceof change_1.InsertChange) {
                    declarationRecorder.insertLeft(change.pos, change.toAdd);
                }
            });
        }
    });
    host.commitUpdate(declarationRecorder);
}
exports.updateModuleChanges = updateModuleChanges;
function getBrowserProjectTargets(host, options) {
    const workspace = (0, workspace_1.getWorkspace)(host);
    const clientProject = (0, project_1.getProject)(workspace, options.project);
    // @ts-ignore: Avoiding strict mode errors, preserving old behavior
    return (0, project_targets_1.getProjectTargets)(clientProject)["build"];
}
exports.getBrowserProjectTargets = getBrowserProjectTargets;
function addStylesToAngularJson(options, stylePaths) {
    return (host, context) => updateJsonFile(host, context, "angular.json", [
        "projects",
        options.project,
        "architect",
        "build",
        "options",
        "styles",
    ], stylePaths);
}
exports.addStylesToAngularJson = addStylesToAngularJson;
function installPackageJsonDependencies() {
    return (host, context) => {
        context.addTask(new tasks_1.NodePackageInstallTask());
        context.logger.info(` Installing packages...`);
        return host;
    };
}
exports.installPackageJsonDependencies = installPackageJsonDependencies;
function assembleDependencies(dependencies) {
    return Object.keys(dependencies).map((key) => ({
        type: dependencies_1.NodeDependencyType.Default,
        version: omitUpperPeerDependencyVersion(dependencies[key]),
        name: key,
        overwrite: true,
    }));
}
exports.assembleDependencies = assembleDependencies;
function omitUpperPeerDependencyVersion(version) {
    return version.split("||")[0].trim();
}
exports.omitUpperPeerDependencyVersion = omitUpperPeerDependencyVersion;
//# sourceMappingURL=schematics-helper.js.map