"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BaseCommand = void 0;
const tslib_1 = require("tslib");
const core_1 = require("@oclif/core");
const config_1 = tslib_1.__importDefault(require("@trello-cli/config"));
const cache_1 = tslib_1.__importDefault(require("@trello-cli/cache"));
const path = tslib_1.__importStar(require("path"));
const trello_js_1 = require("trello.js");
const json2csv_1 = require("json2csv");
const index_1 = require("./index");
class BaseCommand extends core_1.Command {
    constructor(a, b) {
        super(a, b);
        this.defaultOutput = "silent";
        this.lookups = {
            board: "!!! Missing --board Flag !!!",
            list: "!!! Missing --list Flag !!!",
            card: "!!! Missing --card Flag !!!",
            user: "!!! Missing --card Flag !!!",
        };
        const homeDir = process.env[process.platform == "win32" ? "USERPROFILE" : "HOME"];
        this.configDir = path.join(homeDir, ".trello-cli");
        this.profile = process.env.TRELLO_CLI_PROFILE || "default";
        this.trelloConfig = new config_1.default(this.configDir, this.profile);
    }
    async init() {
        var _a;
        await super.init();
        const { flags } = await this.parse(this.ctor);
        this.flags = flags;
        if (((_a = this.id) === null || _a === void 0 ? void 0 : _a.startsWith("auth:")) && this.argv.length) {
            return;
        }
        try {
            const token = await this.trelloConfig.getToken();
            const appKey = await this.trelloConfig.getApiKey();
            this.client = new trello_js_1.TrelloClient({
                key: appKey,
                token: token,
            });
            this.cache = new cache_1.default(path.join(this.configDir, this.profile), appKey, token);
            // Auto-translate any `board` and `list` entries in this.flags
            if (this.flags.board) {
                this.lookups.board = await this.cache.getBoardIdByName(this.flags.board);
            }
            if (this.flags.list) {
                this.lookups.list = await this.cache.getListIdByBoardAndName(this.lookups.board, this.flags.list);
            }
            if (this.flags.user) {
                this.lookups.user = await this.cache.getUserIdByName(this.flags.user);
                if (!this.lookups.user) {
                    this.lookups.user = this.flags.user;
                }
            }
            if (this.flags.card && this.flags.list) {
                let cards = await this.client.lists.getListCards({
                    id: this.lookups.list,
                });
                cards = cards.filter((c) => this.flags.card == c.name);
                if (cards.length > 1) {
                    throw new Error(`Found multiple cards with the name '${this.flags.card}'`);
                }
                if (cards.length < 1) {
                    throw new Error(`Found no cards with the name '${this.flags.card}'`);
                }
                this.lookups.card = cards[0].id;
            }
            else {
                this.lookups.card = this.flags.card;
            }
        }
        catch (e) {
            // If we're in debug mode, don't show how to generate credentials
            if (this.id == "debug") {
                return;
            }
            let cmd = this.config.bin;
            if (process.env.TRELLO_CLI_PROFILE) {
                cmd = `TRELLO_CLI_PROFILE=${process.env.TRELLO_CLI_PROFILE} ${cmd}`;
            }
            const message = e.message || e;
            if (e.code == "ERR_NO_APP_KEY") {
                this.warn(`Visit ${e.data.url} to get an API key then run '${cmd} auth:api-key YOUR_API_KEY'`);
            }
            else if (e.code == "ERR_NO_TOKEN") {
                this.warn(e.message);
                this.logToStderr(`\nVisit ${e.data.url} to generate a token\n\nNext, run '${cmd} auth:token YOUR_TOKEN'`);
            }
            else {
                this.warn(message);
            }
            this.exit(1);
        }
    }
    async output(data) {
        var _a;
        let format = (_a = this.flags.format) !== null && _a !== void 0 ? _a : "default";
        if (format === "default") {
            format = this.defaultOutput;
        }
        if (format == "silent") {
            return;
        }
        const d = await this.toData(data);
        if (format == "json") {
            return this.log(JSON.stringify(d, null, 2));
        }
        if (format == "csv") {
            return this.log(this.outputCsv(d));
        }
        if (format == "fancy") {
            return this.log(await this.format(d));
        }
        // Not user controllable - may be set as the default for a command
        if (format == "raw") {
            return this.log(d);
        }
    }
    toData(data) {
        return data;
    }
    outputCsv(data) {
        let keyEntry = data;
        if (Array.isArray(data)) {
            keyEntry = data[0];
        }
        const fields = Object.keys(keyEntry);
        const opts = { fields };
        return (0, json2csv_1.parse)(data, opts);
    }
    async format(_data) {
        throw new Error(`format not implemented for [${this.id}]`);
    }
    async run() {
        await (0, index_1.run)([this.id, "--help"]);
    }
    async catch(err) {
        // add any custom logic to handle errors from the command
        // or simply return the parent class error handling
        return super.catch(err);
    }
    async finally(_) {
        // called after run and catch regardless of whether or not the command errored
        return super.finally(_);
    }
}
exports.BaseCommand = BaseCommand;
// define flags that can be inherited by any command that extends BaseCommand
BaseCommand.baseFlags = {
    format: core_1.Flags.option({
        options: ["default", "silent", "json", "csv"],
        default: "default",
        description: "Output format",
    })(),
};
