"use strict";
const constants = require("../constants");
const semver = require("semver");
const path = require("path");
const helpers_1 = require("../common/helpers");
class VersionsService {
    constructor($fs, $npmInstallationManager, $injector, $staticConfig, $pluginsService) {
        this.$fs = $fs;
        this.$npmInstallationManager = $npmInstallationManager;
        this.$injector = $injector;
        this.$staticConfig = $staticConfig;
        this.$pluginsService = $pluginsService;
        this.projectData = this.getProjectData();
    }
    getNativescriptCliVersion() {
        return (() => {
            let currentCliVersion = this.$staticConfig.version;
            let latestCliVersion = this.$npmInstallationManager.getLatestVersion(constants.NATIVESCRIPT_KEY_NAME).wait();
            return {
                componentName: constants.NATIVESCRIPT_KEY_NAME,
                currentVersion: currentCliVersion,
                latestVersion: latestCliVersion
            };
        }).future()();
    }
    getTnsCoreModulesVersion() {
        return (() => {
            let latestTnsCoreModulesVersion = this.$npmInstallationManager.getLatestVersion(constants.TNS_CORE_MODULES_NAME).wait();
            let nativescriptCoreModulesInfo = {
                componentName: constants.TNS_CORE_MODULES_NAME,
                latestVersion: latestTnsCoreModulesVersion
            };
            if (this.projectData) {
                let nodeModulesPath = path.join(this.projectData.projectDir, constants.NODE_MODULES_FOLDER_NAME);
                let tnsCoreModulesPath = path.join(nodeModulesPath, constants.TNS_CORE_MODULES_NAME);
                if (!this.$fs.exists(nodeModulesPath).wait() ||
                    !this.$fs.exists(tnsCoreModulesPath).wait()) {
                    this.$pluginsService.ensureAllDependenciesAreInstalled().wait();
                }
                let currentTnsCoreModulesVersion = this.$fs.readJson(path.join(tnsCoreModulesPath, constants.PACKAGE_JSON_FILE_NAME)).wait().version;
                nativescriptCoreModulesInfo.currentVersion = currentTnsCoreModulesVersion;
            }
            return nativescriptCoreModulesInfo;
        }).future()();
    }
    getRuntimesVersions() {
        return (() => {
            let runtimes = [
                constants.TNS_ANDROID_RUNTIME_NAME,
                constants.TNS_IOS_RUNTIME_NAME
            ];
            let projectConfig;
            if (this.projectData) {
                projectConfig = this.$fs.readJson(this.projectData.projectFilePath).wait();
            }
            let runtimesVersions = runtimes.map((runtime) => {
                let latestRuntimeVersion = this.$npmInstallationManager.getLatestVersion(runtime).wait();
                let runtimeInformation = {
                    componentName: runtime,
                    latestVersion: latestRuntimeVersion
                };
                if (projectConfig) {
                    let projectRuntimeInformation = projectConfig.nativescript && projectConfig.nativescript[runtime];
                    if (projectRuntimeInformation) {
                        let runtimeVersionInProject = projectRuntimeInformation.version;
                        runtimeInformation.currentVersion = runtimeVersionInProject;
                    }
                }
                return runtimeInformation;
            });
            return runtimesVersions;
        }).future()();
    }
    getComponentsForUpdate() {
        return (() => {
            let allComponents = this.getAllComponentsVersions().wait();
            let componentsForUpdate = [];
            _.forEach(allComponents, (component) => {
                if (component.currentVersion && this.hasUpdate(component)) {
                    componentsForUpdate.push(component);
                }
            });
            return componentsForUpdate;
        }).future()();
    }
    getAllComponentsVersions() {
        return (() => {
            let allComponents = [];
            let nativescriptCliInformation = this.getNativescriptCliVersion().wait();
            if (nativescriptCliInformation) {
                allComponents.push(nativescriptCliInformation);
            }
            let nativescriptCoreModulesInformation = this.getTnsCoreModulesVersion().wait();
            if (nativescriptCoreModulesInformation) {
                allComponents.push(nativescriptCoreModulesInformation);
            }
            let runtimesVersions = this.getRuntimesVersions().wait();
            allComponents = allComponents.concat(runtimesVersions);
            return allComponents;
        }).future()();
    }
    createTableWithVersionsInformation(versionsInformation) {
        let headers = ["Component", "Current version", "Latest version", "Information"];
        let data = [];
        _.forEach(versionsInformation, (componentInformation) => {
            let row = [
                componentInformation.componentName,
                componentInformation.currentVersion,
                componentInformation.latestVersion
            ];
            if (componentInformation.currentVersion) {
                semver.lt(componentInformation.currentVersion, componentInformation.latestVersion) ? row.push(VersionsService.UPDATE_AVAILABLE_MESSAGE) : row.push(VersionsService.UP_TO_DATE_MESSAGE);
            }
            else {
                row.push(VersionsService.NOT_INSTALLED_MESSAGE);
            }
            data.push(row);
        });
        return helpers_1.createTable(headers, data);
    }
    getProjectData() {
        try {
            return this.$injector.resolve("projectData");
        }
        catch (error) {
            return null;
        }
    }
    hasUpdate(component) {
        return semver.lt(component.currentVersion, component.latestVersion);
    }
}
VersionsService.UP_TO_DATE_MESSAGE = "Up to date".green.toString();
VersionsService.UPDATE_AVAILABLE_MESSAGE = "Update available".yellow.toString();
VersionsService.NOT_INSTALLED_MESSAGE = "Not installed".grey.toString();
$injector.register("versionsService", VersionsService);
