"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PluginLegacy = void 0;
const core_1 = require("@oclif/core");
const path = require("path");
const util_1 = require("util");
const util_2 = require("./util");
const debug = require('debug')('@oclif/plugin-legacy');
const pjson = require('../package.json');
function convertFlagsFromV5(Flags, flags) {
    if (!flags)
        return {};
    if (!Array.isArray(flags))
        return flags;
    // eslint-disable-next-line unicorn/no-array-reduce
    return flags.reduce((flags, flag) => {
        const opts = {
            char: flag.char,
            completion: flag.completion,
            default: flag.default,
            description: flag.description,
            hidden: flag.hidden,
            parse: flag.parse,
            required: flag.required || flag.optional === false,
        };
        for (const [k, v] of Object.entries(opts)) {
            if (v === undefined)
                delete opts[k];
        }
        if (!opts.parse)
            delete opts.parse;
        flags[flag.name] = flag.hasValue ? Flags.string(opts) : Flags.boolean(opts);
        return flags;
    }, {});
}
class PluginLegacy extends core_1.Plugin {
    constructor(config, base) {
        super(base);
        this.config = config;
        this.base = base;
        this._base = `${pjson.name}@${pjson.version}`;
        debug('loading legacy plugin', base.root);
    }
    get moduleCommands() {
        if (this._moduleCommands)
            return this._moduleCommands;
        const { main } = this.pjson;
        if (!main)
            return [];
        const module = require(path.join(this.root, main));
        if (!module.commands)
            return [];
        debug('loading module commands', this.root);
        this._moduleCommands = module.commands.map((c) => this.convertCommand(c));
        return this._moduleCommands;
    }
    get moduleTopics() {
        if (this.pjson.oclif.topics)
            return [];
        if (this._moduleTopics)
            return this._moduleTopics;
        const { main } = this.pjson;
        if (!main)
            return [];
        const module = require(path.join(this.root, main));
        if (!module.commands)
            return [];
        debug('loading module topics', this.root);
        this._moduleTopics = module.topics;
        return this._moduleTopics;
    }
    get topics() {
        return super.topics.concat(this.moduleTopics);
    }
    async findCommand(id, opts = {}) {
        let cmd = await super.findCommand(id);
        if (cmd)
            return this.convertCommand(cmd);
        cmd = this.moduleCommands.find((c) => c.id === id);
        if (cmd) {
            cmd.plugin = this;
            return this.convertCommand(cmd);
        }
        if (opts.must)
            throw new Error(`command ${id} not found`);
    }
    async getCommandIds() {
        return [
            // @ts-expect-error because it's private
            ...(await super.getCommandIds()),
            ...this.moduleCommands.map((c) => c.id),
        ];
    }
    convertCommand(c) {
        if (this.isICommand(c))
            return this.convertFromICommand(c);
        if (this.isV5Command(c))
            return this.convertFromV5(c);
        if (this.isFlowCommand(c))
            return this.convertFromFlow(c);
        debug(c);
        throw new Error(`Invalid command: ${(0, util_1.inspect)(c)}`);
    }
    convertFromFlow(c) {
        if (!c.id)
            c.id = (0, util_2.compact)([c.topic, c.command]).join(':');
        c._version = c._version || '0.0.0';
        return c;
    }
    convertFromICommand(c) {
        if (!c.id)
            c.id = (0, util_2.compact)([c.topic, c.command]).join(':');
        return c;
    }
    convertFromV5(c) {
        const { Command, flags: Flags, vars } = require('@heroku-cli/command');
        class V5 extends Command {
            async run() {
                const color = require('@oclif/color').default;
                const { args, argv, flags } = await this.parse(this.constructor);
                const ctx = {
                    apiHost: vars.apiHost,
                    apiToken: this.heroku.auth,
                    apiUrl: vars.apiUrl,
                    app: flags.app,
                    args: c.variableArgs ? argv : args,
                    auth: {},
                    config: this.config,
                    cwd: process.cwd(),
                    debug: Boolean(this.config.debug),
                    debugHeaders: this.config.debug > 1 || ['1', 'true'].includes(process.env.HEROKU_DEBUG_HEADERS),
                    flags,
                    gitHost: vars.gitHost,
                    herokuDir: this.config.cacheDir,
                    httpGitHost: vars.httpGitHost,
                    org: flags.org,
                    supportsColor: Boolean(color.supports.stdout),
                    team: flags.team,
                    version: this.config.userAgent,
                };
                ctx.auth.password = ctx.apiToken;
                const ansi = require('ansi-escapes');
                process.once('exit', () => {
                    if (process.stderr.isTTY) {
                        process.stderr.write(ansi.cursorShow);
                    }
                });
                return c.run(ctx);
            }
        }
        V5.aliases = c.aliases || [];
        // eslint-disable-next-line unicorn/consistent-function-scoping
        V5.args = (c.args || []).map((a) => (Object.assign(Object.assign({}, a), { required: a.required !== false && !a.optional })));
        V5.description = [c.description, c.help].join('\n');
        V5.examples = c.examples || c.example;
        V5.flags = convertFlagsFromV5(Flags, c.flags);
        V5.help = c.help;
        V5.hidden = Boolean(c.hidden);
        V5.id = (0, util_2.compact)([c.topic, c.command]).join(':');
        V5.strict = c.strict || !c.variableArgs;
        V5.usage = c.usage;
        if (c.needsApp || c.wantsApp) {
            V5.flags.app = Flags.app({ required: Boolean(c.needsApp) });
            V5.flags.remote = Flags.remote();
        }
        if (c.needsOrg || c.wantsOrg) {
            const opts = { description: 'team to use', hidden: false, required: Boolean(c.needsOrg) };
            V5.flags.team = Flags.team(opts);
            V5.flags.org = Flags.team({ char: 'o', hidden: true });
        }
        return V5;
    }
    isFlowCommand(command) {
        const c = command;
        return typeof c === 'function';
        // if (c._version && deps.semver.lt(c._version, '11.0.0')) return true
    }
    isICommand(c) {
        const semver = require('semver');
        if (!c._version)
            return false;
        return semver.gte(c._version, '11.0.0');
    }
    isV5Command(command) {
        const c = command;
        return Boolean(typeof c === 'object');
    }
}
exports.PluginLegacy = PluginLegacy;
