// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'dart:async';
import 'dart:io' show File;

import 'package:args/args.dart';
import 'package:dartdev/src/generate_kernel.dart';
import 'package:frontend_server/resident_frontend_server_utils.dart'
    show ResidentCompilerInfo;

import '../core.dart';
import '../resident_frontend_constants.dart';
import '../resident_frontend_utils.dart';

class CompilationServerCommand extends DartdevCommand {
  static const commandName = 'compilation-server';

  static const commandDescription = 'Control resident frontend compilers.';

  static const legacyResidentServerInfoFileFlag = 'resident-server-info-file';
  static const residentCompilerInfoFileFlag = residentCompilerInfoFileOption;
  static const residentCompilerInfoFileFlagDescription =
      'The path to an info file that the Dart CLI will use to communicate with '
      'a resident frontend compiler. Each unique info file is associated with '
      'a unique resident frontend compiler. If this flag is ommitted, the '
      'default info file will be used.';

  static const inaccessibleDefaultResidentCompilerInfoFileMessage =
      'The default resident frontend compiler info file could not be accessed. '
      'Please explicitly provide the path to a resident compiler info file '
      'using the --resident-compiler-info-file option.';

  CompilationServerCommand({bool verbose = false})
      : super(
          commandName,
          commandDescription,
          false,
          hidden: !verbose,
        ) {
    addSubcommand(CompilationServerStartCommand());
    addSubcommand(CompilationServerShutdownCommand());
  }

  @override
  CommandCategory get commandCategory => CommandCategory.tools;
}

class CompilationServerStartCommand extends DartdevCommand {
  static const commandName = 'start';

  static const commandDescription = 'Start a resident frontend compiler.';

  CompilationServerStartCommand({bool verbose = false})
      : super(
          commandName,
          commandDescription,
          false,
          hidden: !verbose,
        ) {
    argParser
      ..addOption(
        CompilationServerCommand.residentCompilerInfoFileFlag,
        help: CompilationServerCommand.residentCompilerInfoFileFlagDescription,
      )
      ..addOption(
        CompilationServerCommand.legacyResidentServerInfoFileFlag,
        // This option is only available for backwards compatibility, and should
        // never be shown in the help message.
        hide: true,
      );
  }

  @override
  FutureOr<int> run() async {
    final args = argResults!;

    final File? residentCompilerInfoFile =
        getResidentCompilerInfoFileConsideringArgs(args);
    if (residentCompilerInfoFile == null) {
      log.stderr(
        CompilationServerCommand
            .inaccessibleDefaultResidentCompilerInfoFileMessage,
      );
      return DartdevCommand.errorExitCode;
    }

    try {
      await ensureCompilationServerIsRunning(
        residentCompilerInfoFile,
        quiet: false,
      );
    } catch (e) {
      // We already print the error in `ensureCompilationServerIsRunning` when we
      // throw a state error.
      if (e is! StateError) {
        print(e.toString());
      }
      return 64;
    }
    return 0;
  }
}

class CompilationServerShutdownCommand extends DartdevCommand {
  static const commandName = 'shutdown';

  static const commandDescription = '''
Shut down a resident frontend compiler.

Note that this command name and usage could change as we evolve the resident frontend compiler behavior.''';

  CompilationServerShutdownCommand({bool verbose = false})
      : super(commandName, commandDescription, false, hidden: !verbose) {
    argParser
      ..addOption(
        CompilationServerCommand.residentCompilerInfoFileFlag,
        help: CompilationServerCommand.residentCompilerInfoFileFlagDescription,
      )
      ..addOption(
        CompilationServerCommand.legacyResidentServerInfoFileFlag,
        // This option is only available for backwards compatibility, and should
        // never be shown in the help message.
        hide: true,
      );
  }

  // This argument parser is here solely to ensure that VM specific flags are
  // provided before any command and to provide a more consistent help message
  // with the rest of the tool.
  @override
  ArgParser createArgParser() {
    return ArgParser();
  }

  @override
  FutureOr<int> run() async {
    final args = argResults!;

    final File? residentCompilerInfoFile =
        getResidentCompilerInfoFileConsideringArgs(args);
    if (residentCompilerInfoFile == null) {
      log.stderr(
        CompilationServerCommand
            .inaccessibleDefaultResidentCompilerInfoFileMessage,
      );
      return DartdevCommand.errorExitCode;
    }

    if (!residentCompilerInfoFile.existsSync()) {
      log.stdout('No resident frontend compiler instance running.');
      return 0;
    }

    final residentCompilerInfo =
        ResidentCompilerInfo.fromFile(residentCompilerInfoFile);
    final address = residentCompilerInfo.address;
    final port = residentCompilerInfo.port;
    // There is nothing actionable the user can do in response to an error
    // occurring when shutting down. So, we call
    // [shutDownOrForgetResidentFrontendCompiler] here to ensure that when such
    // an error occurs, we don't report it to the user and instead just forget
    // about the compiler that couldn't be shut down.
    await shutDownOrForgetResidentFrontendCompiler(residentCompilerInfoFile);
    log.stdout(
      'The Resident Frontend Compiler instance at ${address.host}:$port was '
      'successfully shutdown.',
    );
    return 0;
  }
}
