"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.removeWithReceipt = exports.deploy = void 0;
const airnode_node_1 = require("@api3/airnode-node");
const promise_utils_1 = require("@api3/promise-utils");
const chalk_1 = require("chalk");
const infrastructure_1 = require("../infrastructure");
const utils_1 = require("../utils");
const logger = __importStar(require("../utils/logger"));
const infrastructure_2 = require("../utils/infrastructure");
function deploy(configPath, secretsPath, receiptFile, autoRemove) {
    return __awaiter(this, void 0, void 0, function* () {
        const secrets = (0, utils_1.parseSecretsFile)(secretsPath);
        const config = (0, airnode_node_1.loadConfig)(configPath, secrets);
        if (config.nodeSettings.cloudProvider.type === 'local') {
            throw (0, infrastructure_2.logAndReturnError)(`Deployer can't deploy to "local" cloud provider`);
        }
        // Deployment is not an atomic operation. It is possible that some resources are deployed even when there is a
        // deployment error. We want to write a receipt file, because the user might use the receipt to remove the deployed
        // resources from the failed deployment. (The removal is not guaranteed, but it's better compared to asking user to
        // remove the resources manually in the cloud provider dashboard).
        const goDeployAirnode = yield (0, promise_utils_1.go)(() => (0, infrastructure_1.deployAirnode)(config, configPath, secretsPath));
        (0, utils_1.writeReceiptFile)(receiptFile, config, goDeployAirnode.success);
        if (!goDeployAirnode.success && !autoRemove) {
            logger.fail((0, chalk_1.bold)(`Airnode deployment failed due to unexpected errors.\n` +
                `  It is possible that some resources have been deployed on cloud provider.\n` +
                `  Please use the "remove" command from the deployer CLI to ensure all cloud resources are removed.`));
            throw goDeployAirnode.error;
        }
        if (!goDeployAirnode.success) {
            logger.fail((0, chalk_1.bold)(`Airnode deployment failed due to unexpected errors.\n` +
                `  It is possible that some resources have been deployed on cloud provider.\n` +
                `  Attempting to remove them...\n`));
            // Try to remove deployed resources
            const goRemoveAirnode = yield (0, promise_utils_1.go)(() => removeWithReceipt(receiptFile));
            if (!goRemoveAirnode.success) {
                logger.fail((0, chalk_1.bold)(`Airnode removal failed due to unexpected errors.\n` +
                    `  It is possible that some resources have been deployed on cloud provider.\n` +
                    `  Please check the resources on the cloud provider dashboard and\n` +
                    `  use the "remove" command from the deployer CLI to remove them.\n` +
                    `  If the automatic removal via CLI fails, remove the resources manually.`));
                throw new infrastructure_2.MultiMessageError([
                    'Deployment error:\n' + goDeployAirnode.error.message,
                    'Removal error:\n' + goRemoveAirnode.error.message,
                ]);
            }
            logger.succeed('Successfully removed the Airnode deployment');
            throw new Error('Deployment error:\n' + goDeployAirnode.error.message);
        }
        const output = goDeployAirnode.data;
        if (output.httpGatewayUrl)
            logger.info(`HTTP gateway URL: ${output.httpGatewayUrl}`);
        if (output.httpSignedDataGatewayUrl)
            logger.info(`HTTP signed data gateway URL: ${output.httpSignedDataGatewayUrl}`);
    });
}
exports.deploy = deploy;
function removeWithReceipt(receiptFilename) {
    return __awaiter(this, void 0, void 0, function* () {
        const receipt = (0, utils_1.parseReceiptFile)(receiptFilename);
        const { cloudProvider, stage } = receipt.deployment;
        const airnodeAddress = receipt.airnodeWallet.airnodeAddress;
        // If the function throws, the CLI will fail with a non zero status code
        yield (0, infrastructure_1.removeAirnode)(airnodeAddress, stage, cloudProvider);
    });
}
exports.removeWithReceipt = removeWithReceipt;
//# sourceMappingURL=commands.js.map