"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ProjectData = void 0;
const constants = require("./constants");
const path = require("path");
const _ = require("lodash");
const helpers_1 = require("./common/helpers");
const os_1 = require("os");
const decorators_1 = require("./common/decorators");
const yok_1 = require("./common/yok");
class ProjectData {
    get projectId() {
        this.warnProjectId();
        return this.projectIdentifiers.ios;
    }
    //just in case hook/extension modifies it.
    set projectId(identifier) {
        this.warnProjectId();
        this.projectIdentifiers.ios = identifier;
        this.projectIdentifiers.android = identifier;
        this.projectIdentifiers.visionos = identifier;
    }
    constructor($fs, $errors, $projectHelper, $staticConfig, $options, $logger, $injector, $androidResourcesMigrationService, $devicePlatformsConstants) {
        this.$fs = $fs;
        this.$errors = $errors;
        this.$projectHelper = $projectHelper;
        this.$staticConfig = $staticConfig;
        this.$options = $options;
        this.$logger = $logger;
        this.$injector = $injector;
        this.$androidResourcesMigrationService = $androidResourcesMigrationService;
        this.$devicePlatformsConstants = $devicePlatformsConstants;
    }
    get projectConfig() {
        return this.$injector.resolve("projectConfigService");
    }
    initializeProjectData(projectDir) {
        if (this.initialized) {
            return;
        }
        projectDir = projectDir || this.$projectHelper.projectDir;
        // If no project found, projectDir should be null
        if (projectDir) {
            const projectFilePath = this.getProjectFilePath(projectDir);
            if (this.$fs.exists(projectFilePath)) {
                const packageJsonContent = this.$fs.readText(projectFilePath);
                this.initializeProjectDataFromContent(packageJsonContent, projectDir);
                this.initialized = true;
            }
            return;
        }
        this.errorInvalidProject(projectDir);
    }
    initializeProjectDataFromContent(packageJsonContent, projectDir) {
        projectDir = projectDir || this.$projectHelper.projectDir || "";
        this.projectDir = projectDir;
        const projectFilePath = this.getProjectFilePath(projectDir);
        const nsConfig = this.projectConfig.readConfig(projectDir);
        let packageJsonData = null;
        try {
            packageJsonData = (0, helpers_1.parseJson)(packageJsonContent);
        }
        catch (err) {
            this.$errors.fail(`The project file ${this.projectFilePath} is corrupted. ${os_1.EOL}` +
                `Consider restoring an earlier version from your source control or backup.${os_1.EOL}` +
                `Additional technical info: ${err.toString()}`);
        }
        if (packageJsonData) {
            this.projectName = this.$projectHelper.sanitizeName(path.basename(projectDir));
            this.platformsDir = path.join(projectDir, constants.PLATFORMS_DIR_NAME);
            this.projectFilePath = projectFilePath;
            this.projectIdentifiers = this.initializeProjectIdentifiers(nsConfig);
            this.packageJsonData = packageJsonData;
            this.dependencies = packageJsonData.dependencies;
            this.devDependencies = packageJsonData.devDependencies;
            this.projectType = this.getProjectType();
            this.nsConfig = nsConfig;
            this.ignoredDependencies = nsConfig === null || nsConfig === void 0 ? void 0 : nsConfig.ignoredNativeDependencies;
            this.appDirectoryPath = this.getAppDirectoryPath();
            this.appResourcesDirectoryPath = this.getAppResourcesDirectoryPath();
            this.androidManifestPath = this.getPathToAndroidManifest(this.appResourcesDirectoryPath);
            this.gradleFilesDirectoryPath = path.join(this.appResourcesDirectoryPath, this.$devicePlatformsConstants.Android);
            this.appGradlePath = path.join(this.gradleFilesDirectoryPath, constants.APP_GRADLE_FILE_NAME);
            this.infoPlistPath = path.join(this.appResourcesDirectoryPath, this.$devicePlatformsConstants.iOS, constants.INFO_PLIST_FILE_NAME);
            this.buildXcconfigPath = path.join(this.appResourcesDirectoryPath, this.$devicePlatformsConstants.iOS, constants.BUILD_XCCONFIG_FILE_NAME);
            this.podfilePath = path.join(this.appResourcesDirectoryPath, this.$devicePlatformsConstants.iOS, constants.PODFILE_NAME);
            this.isShared = !!(this.nsConfig && this.nsConfig.shared);
            this.webpackConfigPath =
                this.nsConfig && this.nsConfig.webpackConfigPath
                    ? path.resolve(this.projectDir, this.nsConfig.webpackConfigPath)
                    : path.join(this.projectDir, "webpack.config.js");
            return;
        }
        this.errorInvalidProject(projectDir);
    }
    getPathToAndroidManifest(appResourcesDir) {
        const androidDirPath = path.join(appResourcesDir, this.$devicePlatformsConstants.Android);
        const androidManifestDir = this.$androidResourcesMigrationService.hasMigrated(appResourcesDir)
            ? path.join(androidDirPath, constants.SRC_DIR, constants.MAIN_DIR)
            : androidDirPath;
        return path.join(androidManifestDir, constants.MANIFEST_FILE_NAME);
    }
    errorInvalidProject(projectDir) {
        const currentDir = path.resolve(".");
        this.$logger.trace(`Unable to find project. projectDir: ${projectDir}, options.path: ${this.$options.path}, ${currentDir}`);
        // This is the case when no project file found
        this.$errors.fail("No project found at or above '%s' and neither was a --path specified.", projectDir || this.$options.path || currentDir);
    }
    getProjectFilePath(projectDir) {
        return path.join(projectDir, this.$staticConfig.PROJECT_FILE_NAME);
    }
    getAppResourcesDirectoryPath(projectDir) {
        const appResourcesRelativePath = this.getAppResourcesRelativeDirectoryPath();
        return this.resolveToProjectDir(appResourcesRelativePath, projectDir);
    }
    getAppResourcesRelativeDirectoryPath() {
        if (this.nsConfig &&
            this.nsConfig[constants.CONFIG_NS_APP_RESOURCES_ENTRY]) {
            return this.nsConfig[constants.CONFIG_NS_APP_RESOURCES_ENTRY];
        }
        return constants.APP_RESOURCES_FOLDER_NAME;
        // return path.join(
        // 	this.getAppDirectoryRelativePath(),
        // 	constants.APP_RESOURCES_FOLDER_NAME
        // );
    }
    getAppDirectoryPath(projectDir) {
        const appRelativePath = this.getAppDirectoryRelativePath();
        return this.resolveToProjectDir(appRelativePath, projectDir);
    }
    getAppDirectoryRelativePath() {
        if (this.nsConfig && this.nsConfig[constants.CONFIG_NS_APP_ENTRY]) {
            return this.nsConfig[constants.CONFIG_NS_APP_ENTRY];
        }
        if (this.$fs.exists(path.resolve(this.projectDir, constants.SRC_DIR))) {
            return constants.SRC_DIR;
        }
        else {
            // legacy project setup often uses app folder
            return constants.APP_FOLDER_NAME;
        }
    }
    getNsConfigRelativePath() {
        return constants.CONFIG_FILE_NAME_JS;
    }
    resolveToProjectDir(pathToResolve, projectDir) {
        if (!projectDir) {
            projectDir = this.projectDir;
        }
        if (!projectDir) {
            return null;
        }
        return path.resolve(projectDir, pathToResolve);
    }
    initializeProjectIdentifiers(config) {
        this.$logger.trace(`Initializing project identifiers. Config: `, config);
        if (!config) {
            this.$logger.error("Unable to determine app id.");
            return {
                ios: "",
                android: "",
                visionos: "",
            };
        }
        const identifier = {
            ios: config.id,
            android: config.id,
            visionos: config.id,
        };
        if (config.ios && config.ios.id) {
            identifier.ios = config.ios.id;
        }
        if (config.android && config.android.id) {
            identifier.android = config.android.id;
        }
        if (config.visionos && config.visionos.id) {
            identifier.visionos = config.visionos.id;
        }
        return identifier;
    }
    getProjectType() {
        let detectedProjectType = _.find(ProjectData.PROJECT_TYPES, (projectType) => projectType.isDefaultProjectType).type;
        const deps = _.keys(this.dependencies).concat(_.keys(this.devDependencies));
        _.each(ProjectData.PROJECT_TYPES, (projectType) => {
            if (_.some(projectType.requiredDependencies, (requiredDependency) => deps.indexOf(requiredDependency) !== -1)) {
                detectedProjectType = projectType.type;
                return false;
            }
        });
        return detectedProjectType;
    }
    warnProjectId() {
        this.$logger.warn("[WARNING]: IProjectData.projectId is deprecated. Please use IProjectData.projectIdentifiers[platform].");
    }
}
/**
 * NOTE: Order of the elements is important as the TypeScript dependencies are commonly included in Angular project as well.
 */
ProjectData.PROJECT_TYPES = [
    {
        type: constants.ProjectTypes.JsFlavorName,
        isDefaultProjectType: true,
    },
    {
        type: constants.ProjectTypes.NgFlavorName,
        requiredDependencies: [
            "@angular/core",
            "nativescript-angular",
            "@nativescript/angular",
        ],
    },
    {
        type: constants.ProjectTypes.VueFlavorName,
        requiredDependencies: ["nativescript-vue"],
    },
    {
        type: constants.ProjectTypes.ReactFlavorName,
        requiredDependencies: ["react-nativescript"],
    },
    {
        type: constants.ProjectTypes.SvelteFlavorName,
        requiredDependencies: ["svelte-native"],
    },
    {
        type: constants.ProjectTypes.TsFlavorName,
        requiredDependencies: ["typescript", "nativescript-dev-typescript"],
    },
];
__decorate([
    (0, decorators_1.cache)()
], ProjectData.prototype, "initializeProjectIdentifiers", null);
__decorate([
    (0, decorators_1.cache)()
], ProjectData.prototype, "warnProjectId", null);
exports.ProjectData = ProjectData;
yok_1.injector.register("projectData", ProjectData, true);
//# sourceMappingURL=project-data.js.map