// SPDX-License-Identifier: Apache-2.0
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;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
import * as constants from './constants.js';
import chalk from 'chalk';
import { SoloError } from './errors/solo-error.js';
import { inject, injectable } from 'tsyringe-neo';
import { patchInject } from './dependency-injection/container-helper.js';
import { InjectTokens } from './dependency-injection/inject-tokens.js';
import { Repository } from '../integration/helm/model/repository.js';
import { UpgradeChartOptions } from '../integration/helm/model/upgrade/upgrade-chart-options.js';
import { Chart } from '../integration/helm/model/chart.js';
import { InstallChartOptionsBuilder } from '../integration/helm/model/install/install-chart-options-builder.js';
import { UnInstallChartOptionsBuilder } from '../integration/helm/model/install/un-install-chart-options-builder.js';
import { AddRepoOptionsBuilder } from '../integration/helm/model/add/add-repo-options-builder.js';
let ChartManager = class ChartManager {
    helm;
    logger;
    constructor(helm, logger) {
        this.helm = helm;
        this.logger = logger;
        this.helm = patchInject(helm, InjectTokens.Helm, this.constructor.name);
        this.logger = patchInject(logger, InjectTokens.SoloLogger, this.constructor.name);
    }
    /**
     * Setup chart repositories
     *
     * This must be invoked before calling other methods
     *
     * @param repoURLs - a map of name and chart repository URLs
     * @param force - whether or not to update the repo
     * @returns the urls
     */
    async setup(repoURLs = constants.DEFAULT_CHART_REPO, force = true) {
        try {
            const promises = [];
            for (const [name, url] of repoURLs.entries()) {
                this.logger.debug(`pushing promise for: add repo ${name} -> ${url}`);
                promises.push(this.addRepo(name, url, force));
            }
            return await Promise.all(promises); // urls
        }
        catch (error) {
            throw new SoloError(`failed to setup chart repositories: ${error.message}`, error);
        }
    }
    /**
     * Check if the required chart repositories are set up
     *
     * @param repoURLs - a map of name and chart repository URLs
     * @returns true if all repos are set up, false otherwise
     */
    async isSetup(repoURLs = constants.DEFAULT_CHART_REPO) {
        try {
            const existingRepos = await this.helm.listRepositories();
            for (const [name, url] of repoURLs.entries()) {
                const found = existingRepos.find((repo) => repo.name === name && repo.url === url);
                if (!found) {
                    this.logger.debug(`Repo not found: ${name} -> ${url}`);
                    return false;
                }
            }
            return true;
        }
        catch (error) {
            throw new SoloError(`failed to check chart repositories: ${error.message}`, error);
        }
    }
    async addRepo(name, url, force) {
        this.logger.debug(`Adding repo ${name} -> ${url}`, { repoName: name, repoURL: url });
        const options = new AddRepoOptionsBuilder().forceUpdate(force).build();
        await this.helm.addRepository(new Repository(name, url), options);
        return url;
    }
    /** List available clusters
     *
     * @param namespaceName - the namespace name
     * @param kubeContext - the kube context
     */
    async getInstalledCharts(namespaceName, kubeContext) {
        try {
            const result = await this.helm.listReleases(!namespaceName, namespaceName?.name, kubeContext);
            // convert to string[]
            return result.map(release => `${release.name} [${release.chart}]`);
        }
        catch (error) {
            this.logger.showUserError(error);
            throw new SoloError(`failed to list installed charts: ${error.message}`, error);
        }
    }
    async install(namespaceName, chartReleaseName, chartName, repoName, version, valuesArgument = '', kubeContext) {
        try {
            const isInstalled = await this.isChartInstalled(namespaceName, chartReleaseName, kubeContext);
            if (isInstalled) {
                this.logger.debug(`OK: chart is already installed:${chartReleaseName} (${chartName}) (${repoName})`);
            }
            else {
                this.logger.debug(`> installing chart:${chartName}`);
                const builder = InstallChartOptionsBuilder.builder()
                    .version(version)
                    .kubeContext(kubeContext)
                    .extraArgs(valuesArgument);
                if (namespaceName) {
                    builder.createNamespace(true);
                    builder.namespace(namespaceName.name);
                }
                const options = builder.build();
                await this.helm.installChart(chartReleaseName, new Chart(chartName, repoName), options);
                this.logger.debug(`OK: chart is installed: ${chartReleaseName} (${chartName}) (${repoName})`);
            }
        }
        catch (error) {
            throw new SoloError(`failed to install chart ${chartReleaseName}: ${error.message}`, error);
        }
        return true;
    }
    async isChartInstalled(namespaceName, chartReleaseName, kubeContext) {
        this.logger.debug(`> checking if chart is installed [ chart: ${chartReleaseName}, namespace: ${namespaceName}, kubeContext: ${kubeContext} ]`);
        const charts = await this.getInstalledCharts(namespaceName, kubeContext);
        let match = false;
        for (const chart of charts) {
            if (chart.split(' ')[0] === chartReleaseName) {
                match = true;
                break;
            }
        }
        return match;
    }
    async uninstall(namespaceName, chartReleaseName, kubeContext) {
        try {
            const isInstalled = await this.isChartInstalled(namespaceName, chartReleaseName, kubeContext);
            if (isInstalled) {
                this.logger.debug(`uninstalling chart release: ${chartReleaseName}`);
                const options = UnInstallChartOptionsBuilder.builder()
                    .namespace(namespaceName.name)
                    .kubeContext(kubeContext)
                    .build();
                await this.helm.uninstallChart(chartReleaseName, options);
                this.logger.debug(`OK: chart release is uninstalled: ${chartReleaseName}`);
            }
            else {
                this.logger.debug(`OK: chart release is already uninstalled: ${chartReleaseName}`);
            }
        }
        catch (error) {
            throw new SoloError(`failed to uninstall chart ${chartReleaseName}: ${error.message}`, error);
        }
        return true;
    }
    async upgrade(namespaceName, chartReleaseName, chartName, repoName, version = '', valuesArgument = '', kubeContext, reuseValues) {
        try {
            this.logger.debug(chalk.cyan('> upgrading chart:'), chalk.yellow(`${chartReleaseName}`));
            const options = new UpgradeChartOptions(namespaceName.name, kubeContext, reuseValues ?? true, valuesArgument, version);
            const chart = new Chart(chartName, repoName);
            await this.helm.upgradeChart(chartReleaseName, chart, options);
            this.logger.debug(chalk.green('OK'), `chart '${chartReleaseName}' is upgraded`);
        }
        catch (error) {
            throw new SoloError(`failed to upgrade chart ${chartReleaseName}: ${error.message}`, error);
        }
        return true;
    }
};
ChartManager = __decorate([
    injectable(),
    __param(0, inject(InjectTokens.Helm)),
    __param(1, inject(InjectTokens.SoloLogger)),
    __metadata("design:paramtypes", [Object, Object])
], ChartManager);
export { ChartManager };
//# sourceMappingURL=chart-manager.js.map