import CommanderCommand              from '../../CommanderCommand';
import Config                        from '../../../config/Config';
import ora                           from 'ora';
import chalk                         from 'chalk';
import AssignmentValidator           from '../../../sharedByClients/helpers/Dojo/AssignmentValidator';
import ClientsSharedAssignmentHelper from '../../../sharedByClients/helpers/Dojo/ClientsSharedAssignmentHelper';
import { Option }                    from 'commander';


class AssignmentCheckCommand extends CommanderCommand {
    protected commandName: string = 'check';

    protected defineCommand() {
        this.command
        .description('locally run a check of an assignment')
        .option('-p, --path <value>', 'assignment path', Config.folders.defaultLocalExercise)
        .option('-v, --verbose', 'verbose mode - display principal container output in live')
        .addOption(new Option('-w, --super-verbose', 'verbose mode - display all docker compose logs (build included) in live').conflicts('verbose'))
        .addOption(new Option('--verbose-ssj2').hideHelp().implies({ superVerbose: true }))
        .action(this.commandAction.bind(this));
    }

    protected async commandAction(options: { path: string, verbose: boolean, superVerbose: boolean }): Promise<void> {
        const verbose: boolean = options.verbose || options.superVerbose;

        const localExercisePath: string = options.path ?? Config.folders.defaultLocalExercise;

        const assignmentValidator = new AssignmentValidator(localExercisePath);

        try {
            await new Promise<void>((resolve, reject) => {
                let spinner: ora.Ora;

                if ( verbose ) {
                    let buildPhase: boolean | undefined = undefined;
                    assignmentValidator.events.on('logs', (log: string, error: boolean, displayable: boolean, _currentStep: string, currentSubStep: string) => {
                        for ( const line of log.split('\n') ) {
                            if ( displayable && buildPhase == undefined && line.startsWith('#') ) {
                                buildPhase = true;
                            }

                            if ( currentSubStep == 'COMPOSE_RUN' && buildPhase === true && line != '' && !line.startsWith('#') ) {
                                buildPhase = false;
                            }

                            if ( displayable && (options.superVerbose || buildPhase === false) ) {
                                console.log(line);
                            }
                        }
                    });
                }

                assignmentValidator.events.on('step', (name: string, message: string) => {
                    console.log(chalk.cyan(message));
                });

                assignmentValidator.events.on('subStep', (name: string, message: string) => {
                    spinner = ora({
                                      text  : message,
                                      indent: 4
                                  }).start();

                    if ( verbose && name == 'COMPOSE_RUN' ) {
                        spinner.info();
                    }
                });

                assignmentValidator.events.on('endSubStep', (stepName: string, message: string, error: boolean) => {
                    if ( error ) {
                        if ( verbose && stepName == 'COMPOSE_RUN' ) {
                            ora({
                                    text  : message,
                                    indent: 4
                                }).start().fail();
                        } else {
                            spinner.fail(message);
                        }
                    } else {
                        if ( verbose && stepName == 'COMPOSE_RUN' ) {
                            ora({
                                    text  : message,
                                    indent: 4
                                }).start().succeed();
                        } else {
                            spinner.succeed(message);
                        }
                    }
                });

                assignmentValidator.events.on('finished', (success: boolean) => {
                    success ? resolve() : reject();
                });

                assignmentValidator.run(true);
            });
        } catch ( error ) { /* empty */ }

        ClientsSharedAssignmentHelper.displayExecutionResults(assignmentValidator, `The assignment is ready to be pushed.`, {
            INFO   : chalk.bold,
            SUCCESS: chalk.green,
            FAILURE: chalk.red
        });
    }
}


export default new AssignmentCheckCommand();