"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.VerifyService = void 0;
/*
 * Copyright 2021 NEM
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
const os = require("os");
const semver = require("semver");
const BootstrapUtils_1 = require("./BootstrapUtils");
const defaultExpectedVersions = {
    node: '12.0.0',
    docker: '18.3.0',
    dockerCompose: '1.25.0',
};
class VerifyService {
    constructor(logger, expectedVersions = {}) {
        this.logger = logger;
        this.semverOptions = { loose: true };
        this.expectedVersions = Object.assign(Object.assign({}, defaultExpectedVersions), expectedVersions);
    }
    async createReport() {
        const lines = [];
        const platform = `${os.type()} - ${os.release()} - ${os.platform()}`;
        lines.push(await this.testNodeJs());
        const docker = await this.testDocker();
        lines.push(docker);
        lines.push(await this.testDockerCompose());
        if (!docker.recommendation)
            lines.push(await this.testDockerRun());
        if (!BootstrapUtils_1.BootstrapUtils.isWindows()) {
            lines.push(await this.testSudo());
        }
        return { lines, platform };
    }
    loadVersion(text) {
        var _a;
        return (_a = text
            .replace(',', '')
            .split(' ')
            .map((word) => {
            const coerce = semver.coerce(word.trim(), this.semverOptions);
            return coerce === null || coerce === void 0 ? void 0 : coerce.raw;
        })
            .find((a) => a)) === null || _a === void 0 ? void 0 : _a.trim();
    }
    async testNodeJs() {
        const header = 'NodeVersion';
        const recommendationUrl = `https://nodejs.org/en/download/package-manager/`;
        const output = process.versions.node;
        return this.verifyInstalledApp(async () => output, header, this.expectedVersions.node, recommendationUrl);
    }
    async testDocker() {
        const header = 'Docker Version';
        const command = 'docker --version';
        const recommendationUrl = `https://docs.docker.com/get-docker/`;
        return this.verifyInstalledApp(async () => await this.loadVersionFromCommand(command), header, this.expectedVersions.docker, recommendationUrl);
    }
    async testDockerCompose() {
        const header = 'Docker Compose Version';
        const command = 'docker-compose --version';
        const recommendationUrl = `https://docs.docker.com/compose/install/`;
        return this.verifyInstalledApp(async () => await this.loadVersionFromCommand(command), header, this.expectedVersions.dockerCompose, recommendationUrl);
    }
    async testDockerRun() {
        const header = 'Docker Run Test';
        const command = 'docker run hello-world';
        const recommendationUrl = `https://www.digitalocean.com/community/questions/how-to-fix-docker-got-permission-denied-while-trying-to-connect-to-the-docker-daemon-socket`;
        try {
            const output = (await BootstrapUtils_1.BootstrapUtils.exec(this.logger, command)).stdout.trim();
            const expectedText = 'Hello from Docker!';
            if (output.indexOf(expectedText) == -1) {
                return {
                    header,
                    message: `Command '${command}' could not be executed: Error: '${expectedText}' not in output text \n${output}`,
                    recommendation: `Please check ${recommendationUrl}`,
                };
            }
            return { header, message: `Command '${command}' executed!` };
        }
        catch (e) {
            return {
                header,
                message: `Command '${command}' could not be executed: Error: ${e.message}`,
                recommendation: `Please check ${recommendationUrl}`,
            };
        }
    }
    async testSudo() {
        const header = 'Sudo User Test';
        if (BootstrapUtils_1.BootstrapUtils.isRoot()) {
            return {
                header,
                message: `Your are running with the sudo user!`,
                recommendation: `Either don't use sudo or create a non sudo user to run Bootstrap.`,
            };
        }
        return { header, message: `Your are not the sudo user!` };
    }
    async loadVersionFromCommand(command) {
        return this.loadVersion((await BootstrapUtils_1.BootstrapUtils.exec(this.logger, command)).stdout.trim());
    }
    async verifyInstalledApp(versionLoader, header, minVersion, recommendationUrl) {
        try {
            const version = await versionLoader();
            if (!version) {
                return {
                    header,
                    message: `Version could not be found! Output: ${versionLoader}`,
                    recommendation: `At least version ${minVersion} is required. Check ${recommendationUrl}`,
                };
            }
            if (semver.lt(version, minVersion, this.semverOptions)) {
                return {
                    header,
                    message: version,
                    recommendation: `At least version ${minVersion} is required. Currently installed version is ${version}. Check ${recommendationUrl}`,
                };
            }
            return { header, message: version };
        }
        catch (e) {
            return {
                header,
                message: `Error: ${e.message}`,
                recommendation: `At least version ${minVersion} is required. Check ${recommendationUrl}`,
            };
        }
    }
}
exports.VerifyService = VerifyService;
