import chalk from 'chalk';
import { Command, Option } from 'commander';
import { kebabCase } from 'lodash-es';
import { convertConfigToOption } from '../lib/internal/index.js';
export default class JHipsterCommand extends Command {
    createCommand(name) {
        return new JHipsterCommand(name);
    }
    addAlias(alias) {
        if (alias) {
            this.alias(alias);
        }
        return this;
    }
    lazyBuildCommand(lazyBuildCommandCallBack) {
        this._lazyBuildCommandCallBack = lazyBuildCommandCallBack;
        return this;
    }
    excessArgumentsCallback(excessArgumentsCallback) {
        this._excessArgumentsCallback = excessArgumentsCallback;
        return this;
    }
    _excessArguments(receivedArgs) {
        if (this._excessArgumentsCallback) {
            this._excessArgumentsCallback(receivedArgs);
        }
        else {
            super._excessArguments(receivedArgs);
        }
    }
    async _parseCommand(operands, unknown) {
        if (this._lazyBuildCommandCallBack) {
            await this._lazyBuildCommandCallBack(operands, unknown);
        }
        return super._parseCommand(operands, unknown);
    }
    addOption(option) {
        if (!option.long || option.required || option.optional) {
            return super.addOption(option);
        }
        if (option.negate) {
            super.addOption(new Option(option.long.replace(/^--no-/, '--')).hideHelp());
        }
        const result = super.addOption(option);
        if (!option.negate) {
            super.addOption(new Option(option.long.replace(/^--/, '--no-')).hideHelp());
        }
        return result;
    }
    addCommandArguments(args) {
        if (Array.isArray(args)) {
            args.forEach(arg => this.argument(arg));
        }
        return this;
    }
    addCommandOptions(opts = []) {
        opts.forEach(opt => this._addCommandOption(opt));
        return this;
    }
    _addCommandOption(opt) {
        const additionalDescription = opt.blueprint ? chalk.yellow(` (blueprint option: ${opt.blueprint})`) : '';
        return this.addOption(new Option(opt.option, opt.desc + additionalDescription).default(opt.default));
    }
    addGeneratorArguments(generatorArgs = []) {
        if (!generatorArgs)
            return this;
        generatorArgs.forEach(argument => {
            let argName = argument.type === Array ? `${argument.name}...` : argument.name;
            argName = argument.required ? `<${argName}>` : `[${argName}]`;
            this.argument(argName, argument.description);
        });
        return this;
    }
    addGeneratorOptions(options, blueprintOptionDescription) {
        Object.entries(options ?? {}).forEach(([key, value]) => {
            this._addGeneratorOption(key, value, blueprintOptionDescription);
        });
        return this;
    }
    addJHipsterArguments(jhipsterArguments) {
        Object.entries(jhipsterArguments ?? {}).forEach(([key, value]) => {
            let argName = value.type === Array ? `${key}...` : key;
            argName = value.required ? `<${argName}>` : `[${argName}]`;
            this.argument(argName, value.description);
        });
        return this;
    }
    addJHipsterOptions(options, blueprintOptionDescription) {
        Object.entries(options).forEach(([key, value]) => {
            this._addGeneratorOption(kebabCase(value.name ?? key), value, blueprintOptionDescription);
        });
        return this;
    }
    addJHipsterConfigs(configs = {}, blueprintOptionDescription) {
        Object.entries(configs).forEach(([name, config]) => {
            const option = convertConfigToOption(name, config);
            if (option) {
                this._addGeneratorOption(kebabCase(option.name), option, blueprintOptionDescription);
            }
        });
        return this;
    }
    _addGeneratorOption(optionName, optionDefinition, additionalDescription = '') {
        if (optionName === 'help') {
            return undefined;
        }
        const longOption = `--${optionName}`;
        const existingOption = this._findOption(longOption);
        if (this._findOption(longOption)) {
            return existingOption;
        }
        let cmdString = '';
        if (optionDefinition.alias) {
            cmdString = `-${optionDefinition.alias}, `;
        }
        cmdString = `${cmdString}${longOption}`;
        if (optionDefinition.type === Array) {
            cmdString = optionDefinition.required !== false ? `${cmdString} <value...>` : `${cmdString} [value...]`;
        }
        else if (optionDefinition.type && optionDefinition.type !== Boolean) {
            cmdString = optionDefinition.required !== false ? `${cmdString} <value>` : `${cmdString} [value]`;
        }
        let defaultDescription = '';
        if (optionDefinition.default !== undefined && (!Array.isArray(optionDefinition.default) || optionDefinition.default.length !== 0)) {
            defaultDescription = ` (default: ${optionDefinition.default})`;
        }
        const option = new Option(cmdString, optionDefinition.description + defaultDescription + additionalDescription).hideHelp(optionDefinition.hide ?? false);
        if (optionDefinition.env) {
            option.env(optionDefinition.env);
        }
        if (optionDefinition.choices && optionDefinition.choices.length > 0) {
            option.choices(optionDefinition.choices);
        }
        return this.addOption(option);
    }
}
