// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
// See LICENSE in the project root for license information.
import { JsonFile, FileSystem, InternalError } from '@rushstack/node-core-library';
import { BaseShrinkwrapFile } from '../base/BaseShrinkwrapFile';
import { DependencySpecifier } from '../DependencySpecifier';
export class NpmShrinkwrapFile extends BaseShrinkwrapFile {
    constructor(shrinkwrapJson) {
        super();
        this._shrinkwrapJson = shrinkwrapJson;
        // Normalize the data
        if (!this._shrinkwrapJson.version) {
            this._shrinkwrapJson.version = '';
        }
        if (!this._shrinkwrapJson.name) {
            this._shrinkwrapJson.name = '';
        }
        if (!this._shrinkwrapJson.dependencies) {
            this._shrinkwrapJson.dependencies = {};
        }
        // Workspaces not supported in NPM
        this.isWorkspaceCompatible = false;
    }
    static loadFromFile(shrinkwrapJsonFilename) {
        try {
            const shrinkwrapContent = FileSystem.readFile(shrinkwrapJsonFilename);
            return NpmShrinkwrapFile.loadFromString(shrinkwrapContent);
        }
        catch (error) {
            if (FileSystem.isNotExistError(error)) {
                return undefined; // file does not exist
            }
            throw new Error(`Error reading "${shrinkwrapJsonFilename}":\n  ${error.message}`);
        }
    }
    static loadFromString(shrinkwrapContent) {
        // strip BOM
        const data = shrinkwrapContent.charCodeAt(0) === 0xfeff ? shrinkwrapContent.slice(1) : shrinkwrapContent;
        // We don't use JsonFile/jju here because shrinkwrap.json is a special NPM file format
        // and typically very large, so we want to load it the same way that NPM does.
        return new NpmShrinkwrapFile(JSON.parse(data));
    }
    /** @override */
    getTempProjectNames() {
        return this._getTempProjectNames(this._shrinkwrapJson.dependencies);
    }
    /** @override */
    serialize() {
        return JsonFile.stringify(this._shrinkwrapJson);
    }
    /** @override */
    getTopLevelDependencyVersion(dependencyName) {
        // First, check under tempProjectName, as this is the first place we look during linking.
        const dependencyJson = NpmShrinkwrapFile.tryGetValue(this._shrinkwrapJson.dependencies, dependencyName);
        if (!dependencyJson) {
            return undefined;
        }
        return DependencySpecifier.parseWithCache(dependencyName, dependencyJson.version);
    }
    /**
     * @param dependencyName the name of the dependency to get a version for
     * @param tempProjectName the name of the temp project to check for this dependency
     * @param versionRange Not used, just exists to satisfy abstract API contract
     * @override
     */
    tryEnsureDependencyVersion(dependencySpecifier, tempProjectName) {
        // First, check under tempProjectName, as this is the first place we look during linking.
        let dependencyJson = undefined;
        const tempDependency = NpmShrinkwrapFile.tryGetValue(this._shrinkwrapJson.dependencies, tempProjectName);
        if (tempDependency && tempDependency.dependencies) {
            dependencyJson = NpmShrinkwrapFile.tryGetValue(tempDependency.dependencies, dependencySpecifier.packageName);
        }
        // Otherwise look at the root of the shrinkwrap file
        if (!dependencyJson) {
            return this.getTopLevelDependencyVersion(dependencySpecifier.packageName);
        }
        return DependencySpecifier.parseWithCache(dependencySpecifier.packageName, dependencyJson.version);
    }
    /** @override */
    getProjectShrinkwrap(project) {
        return undefined;
    }
    /** @override */
    async isWorkspaceProjectModifiedAsync(project, subspace, variant) {
        throw new InternalError('Not implemented');
    }
}
//# sourceMappingURL=NpmShrinkwrapFile.js.map