"use strict";
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());
    });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.setCostModel = exports.costModel = exports.costModels = exports.printCostModels = exports.displayCostModel = exports.displayCostModels = exports.costModelToGraphQL = exports.costModelFromGraphQL = exports.formatCostModel = exports.parseCostModel = exports.parseDeploymentID = void 0;
const common_ts_1 = require("@graphprotocol/common-ts");
const graphql_tag_1 = __importDefault(require("graphql-tag"));
const yaml_1 = __importDefault(require("yaml"));
const table_1 = require("table");
const command_helpers_1 = require("./command-helpers");
exports.parseDeploymentID = (s) => {
    if (s === 'all') {
        return s;
    }
    else {
        return new common_ts_1.SubgraphDeploymentID(s);
    }
};
function nullPassThrough(fn) {
    return (x) => (x === null ? null : fn(x));
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const COST_MODEL_PARSERS = {
    id: x => x,
    deployment: exports.parseDeploymentID,
    model: x => x,
    variables: nullPassThrough(JSON.parse),
};
const COST_MODEL_FORMATTERS = {
    id: x => x,
    deployment: (d) => (typeof d === 'string' ? d : d.ipfsHash),
    model: x => x,
    variables: nullPassThrough(s => JSON.stringify(s, null, 2)),
};
const COST_MODEL_CONVERTERS_FROM_GRAPHQL = {
    id: x => x,
    deployment: exports.parseDeploymentID,
    model: x => x,
    variables: nullPassThrough(JSON.parse),
};
const COST_MODEL_CONVERTERS_TO_GRAPHQL = {
    id: x => x,
    deployment: (x) => x.toString(),
    model: x => x,
    variables: nullPassThrough(JSON.stringify),
};
/**
 * Parses a user-provided cost model into a normalized form.
 */
exports.parseCostModel = (cost) => {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const obj = {};
    for (const [key, value] of Object.entries(cost)) {
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        obj[key] = COST_MODEL_PARSERS[key](value);
    }
    return obj;
};
/**
 * Formats a cost model for display in the console.
 */
exports.formatCostModel = (cost, { variablesAsString }) => {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const obj = {};
    for (const [key, value] of Object.entries(cost)) {
        if (key === 'variables' && !variablesAsString) {
            obj[key] = value;
        }
        else {
            // eslint-disable-next-line @typescript-eslint/no-explicit-any
            obj[key] = COST_MODEL_FORMATTERS[key](value);
        }
    }
    return obj;
};
/**
 * Parses a cost model returned from the indexer management GraphQL
 * API into normalized form.
 */
exports.costModelFromGraphQL = (cost) => {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const obj = {};
    for (const [key, value] of Object.entries(cost)) {
        if (key === '__typename') {
            continue;
        }
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        obj[key] = COST_MODEL_CONVERTERS_FROM_GRAPHQL[key](value);
    }
    return obj;
};
/**
 * Converts a normalized cost model to a representation
 * compatible with the indexer management GraphQL API.
 */
exports.costModelToGraphQL = (cost) => {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const obj = {};
    for (const [key, value] of Object.entries(cost)) {
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        obj[key] = COST_MODEL_CONVERTERS_TO_GRAPHQL[key](value);
    }
    return obj;
};
exports.displayCostModels = (outputFormat, costModels) => outputFormat === 'json'
    ? JSON.stringify(costModels, null, 2)
    : outputFormat === 'yaml'
        ? yaml_1.default.stringify(costModels).trim()
        : costModels.length === 0
            ? 'No data'
            : table_1.table([Object.keys(costModels[0]), ...costModels.map(cost => Object.values(cost))], {
                border: table_1.getBorderCharacters('norc'),
            }).trim();
exports.displayCostModel = (outputFormat, cost) => outputFormat === 'json'
    ? JSON.stringify(cost, null, 2)
    : outputFormat === 'yaml'
        ? yaml_1.default.stringify(cost).trim()
        : table_1.table([Object.keys(cost), Object.values(cost)], {
            border: table_1.getBorderCharacters('norc'),
        }).trim();
exports.printCostModels = (print, outputFormat, deployment, costModelOrModels, fields) => {
    if (Array.isArray(costModelOrModels)) {
        const costModels = costModelOrModels.map(cost => exports.formatCostModel(command_helpers_1.pickFields(cost, fields), {
            variablesAsString: outputFormat === 'table',
        }));
        print.info(exports.displayCostModels(outputFormat, costModels));
    }
    else if (costModelOrModels) {
        const cost = exports.formatCostModel(command_helpers_1.pickFields(costModelOrModels, fields), {
            variablesAsString: outputFormat === 'table',
        });
        print.info(exports.displayCostModel(outputFormat, cost));
    }
    else if (deployment) {
        print.error(`No cost model/variables found for "${deployment}"`);
    }
    else {
        print.error(`No cost models/variables found`);
    }
};
exports.costModels = (client) => __awaiter(void 0, void 0, void 0, function* () {
    const result = yield client
        .query(graphql_tag_1.default `
        {
          costModels {
            deployment
            model
            variables
          }
        }
      `)
        .toPromise();
    if (result.error) {
        throw result.error;
    }
    return result.data.costModels.map(exports.costModelFromGraphQL);
});
exports.costModel = (client, deployment) => __awaiter(void 0, void 0, void 0, function* () {
    const result = yield client
        .query(graphql_tag_1.default `
        query costModel($deployment: String!) {
          costModel(deployment: $deployment) {
            deployment
            model
            variables
          }
        }
      `, { deployment: deployment.toString() })
        .toPromise();
    if (result.error) {
        throw result.error;
    }
    if (result.data.costModel) {
        return exports.costModelFromGraphQL(result.data.costModel);
    }
    else {
        return null;
    }
});
exports.setCostModel = (client, costModel) => __awaiter(void 0, void 0, void 0, function* () {
    const result = yield client
        .mutation(graphql_tag_1.default `
        mutation setCostModel($costModel: CostModelInput!) {
          setCostModel(costModel: $costModel) {
            deployment
            model
            variables
          }
        }
      `, { costModel: exports.costModelToGraphQL(costModel) })
        .toPromise();
    if (result.error) {
        throw result.error;
    }
    return exports.costModelFromGraphQL(result.data.setCostModel);
});
