// Copyright 2014 The Flutter Authors. 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 'package:args/command_runner.dart';
import 'package:intl/intl.dart' as intl;
import 'package:intl/intl_standalone.dart' as intl_standalone;
import 'package:process/process.dart';
import 'package:unified_analytics/unified_analytics.dart';

import 'src/base/async_guard.dart';
import 'src/base/common.dart';
import 'src/base/context.dart';
import 'src/base/error_handling_io.dart';
import 'src/base/exit.dart';
import 'src/base/file_system.dart';
import 'src/base/io.dart';
import 'src/base/logger.dart';
import 'src/base/process.dart';
import 'src/context/tool_dependencies.dart';
import 'src/context_runner.dart';
import 'src/doctor.dart';
import 'src/emulator.dart';
import 'src/features.dart';
import 'src/globals.dart' as globals;
import 'src/reporting/crash_reporting.dart';
import 'src/runner/flutter_command.dart';
import 'src/runner/flutter_command_runner.dart';

/// Runs the Flutter tool with support for the specified list of [commands].
Future<int> run(
  List<String> args,
  List<FlutterCommand> Function(ToolDependencies toolDependencies) commands, {
  required ShutdownHooks shutdownHooks,
  String? flutterVersion,
  bool muteCommandLogging = false,
  Map<Type, Generator>? overrides,
  bool? reportCrashes,
  bool verbose = false,
  bool verboseHelp = false,
}) async {
  if (muteCommandLogging) {
    // Remove the verbose option; for help and doctor, users don't need to see
    // verbose logs.
    args = List<String>.of(args);
    args.removeWhere((String option) => option == '-vv' || option == '-v' || option == '--verbose');
  }

  // Reset this on each run to ensure we don't leak state across tests.
  _alreadyHandlingToolError = null;

  final bool usingLocalEngine = args.any((a) => a.startsWith('--local-engine'));

  return runInContext<int>(() async {
    globals.terminal.applyFeatureFlags(featureFlags);

    reportCrashes ??= !await globals.isRunningOnBot;
    final ToolDependencies toolDeps = await ToolDependencies.bootstrap(
      analytics: globals.analytics,
      androidSdk: globals.androidSdk,
      androidStudio: globals.androidStudio,
      artifacts: globals.artifacts,
      botDetector: globals.botDetector,
      buildSystem: globals.buildSystem,
      buildTargets: globals.buildTargets,
      cache: globals.cache,
      cocoaPods: globals.cocoaPods,
      cocoapodsValidator: globals.cocoapodsValidator,
      config: globals.config,
      crashReporter: globals.crashReporter,
      customDevicesConfig: globals.customDevicesConfig,
      doctor: globals.doctor,
      emulatorManager: emulatorManager,
      featureFlags: featureFlags,
      flutterVersion: globals.flutterVersion,
      fs: globals.fs,
      git: globals.git,
      gradleUtils: globals.gradleUtils,
      iosSimulatorUtils: globals.iosSimulatorUtils,
      iosWorkflow: globals.iosWorkflow,
      java: globals.java,
      localEngineLocator: globals.localEngineLocator,
      logger: globals.logger,
      nativeAssetsBuilder: globals.nativeAssetsBuilder,
      outputPreferences: globals.outputPreferences,
      persistentToolState: globals.persistentToolState,
      platform: globals.platform,
      plistParser: globals.plistParser,
      preRunValidator: globals.preRunValidator,
      processInfo: globals.processInfo,
      processManager: globals.processManager,
      projectFactory: globals.projectFactory,
      shutdownHooks: shutdownHooks,
      stdio: globals.stdio,
      systemClock: globals.systemClock,
      terminal: globals.terminal,
      userMessages: globals.userMessages,
      xcdevice: globals.xcdevice,
      xcode: globals.xcode,
      xcodeProjectInterpreter: globals.xcodeProjectInterpreter,
    );
    final runner = FlutterCommandRunner(
      analytics: toolDeps.analytics,
      featureFlags: featureFlags,
      toolContext: toolDeps.toolContext,
      verboseHelp: verboseHelp,
    );
    commands(toolDeps).forEach(runner.addCommand);

    // Initialize the system locale.
    final String systemLocale = await intl_standalone.findSystemLocale();
    intl.Intl.defaultLocale = intl.Intl.verifiedLocale(
      systemLocale,
      intl.NumberFormat.localeExists,
      onFailure: (String _) => 'en_US',
    );

    String getVersion() =>
        flutterVersion ?? globals.flutterVersion.getVersionString(redactUnknownBranches: true);
    Object? firstError;
    StackTrace? firstStackTrace;
    return runZonedGuarded<Future<int>>(
      () async {
        try {
          if (args.contains('--disable-analytics') && args.contains('--enable-analytics')) {
            throwToolExit(
              'Both enable and disable analytics commands were detected '
              'when only one can be supplied per invocation.',
              exitCode: 1,
            );
          }

          if (args.contains('--disable-analytics')) {
            if (globals.analytics.telemetryEnabled) {
              globals.analytics.send(Event.analyticsCollectionEnabled(status: false));
              // Before disablig analytics, we need to close the client to make
              // sure the above collection event is sent.
              await globals.analytics.close();
            }
            await globals.analytics.setTelemetry(false);
            globals.printStatus('Analytics reporting disabled.');
          }

          if (args.contains('--enable-analytics')) {
            final bool alreadyEnabled = globals.analytics.telemetryEnabled;
            await globals.analytics.setTelemetry(true);
            if (!alreadyEnabled) {
              globals.analytics.send(Event.analyticsCollectionEnabled(status: true));
            }
            globals.printStatus('Analytics reporting enabled.');
          }

          await runner.run(args);

          // Triggering [runZoned]'s error callback does not necessarily mean that
          // we stopped executing the body. See https://github.com/dart-lang/sdk/issues/42150.
          if (firstError == null) {
            return await exitWithHooks(0, shutdownHooks: shutdownHooks);
          }

          // We already hit some error, so don't return success. The error path
          // (which should be in progress) is responsible for calling _exit().
          return 1;
          // This catches all exceptions to send to crash logging, etc.
          // ignore: avoid_catches_without_on_clauses
        } catch (error, stackTrace) {
          firstError = error;
          firstStackTrace = stackTrace;
          return _handleToolError(
            error,
            stackTrace,
            verbose,
            args,
            reportCrashes!,
            getVersion,
            shutdownHooks,
            featureFlags: featureFlags,
            usingLocalEngine: usingLocalEngine,
          );
        }
      },
      (Object error, StackTrace stackTrace) async {
        // If sending a crash report throws an error into the zone, we don't want
        // to re-try sending the crash report with *that* error. Rather, we want
        // to send the original error that triggered the crash report.
        firstError ??= error;
        firstStackTrace ??= stackTrace;
        await _handleToolError(
          firstError!,
          firstStackTrace,
          verbose,
          args,
          reportCrashes!,
          getVersion,
          shutdownHooks,
          featureFlags: featureFlags,
          usingLocalEngine: usingLocalEngine,
        );
      },
    )!;
  }, overrides: overrides);
}

/// Track if we're actively processing an error so we don't try and process
/// additional asynchronous exceptions while we're trying to shut down.
///
/// NOTE: This state is cleared at the beginning of [run] to ensure state
/// doesn't leak when running tests.
Future<int>? _alreadyHandlingToolError;

Future<int> _handleToolError(
  Object error,
  StackTrace? stackTrace,
  bool verbose,
  List<String> args,
  bool reportCrashes,
  String Function() getFlutterVersion,
  ShutdownHooks shutdownHooks, {
  required bool usingLocalEngine,
  required FeatureFlags featureFlags,
}) async {
  return _alreadyHandlingToolError ??= _handleToolErrorImpl(
    error,
    stackTrace,
    verbose,
    args,
    reportCrashes,
    getFlutterVersion,
    shutdownHooks,
    usingLocalEngine: usingLocalEngine,
    featureFlags: featureFlags,
  );
}

Future<int> _handleToolErrorImpl(
  Object error,
  StackTrace? stackTrace,
  bool verbose,
  List<String> args,
  bool reportCrashes,
  String Function() getFlutterVersion,
  ShutdownHooks shutdownHooks, {
  required bool usingLocalEngine,
  required FeatureFlags featureFlags,
}) async {
  if (error is UsageException) {
    globals.printError('${error.message}\n');
    globals.printError(
      "Run 'flutter -h' (or 'flutter <command> -h') for available flutter commands and options.",
    );
    // Argument error exit code.
    return exitWithHooks(64, shutdownHooks: shutdownHooks);
  } else if (error is ToolExit) {
    if (error.message != null) {
      globals.printError(error.message!);
    }
    if (verbose) {
      globals.printError('\n$stackTrace\n');
    }
    return exitWithHooks(error.exitCode ?? 1, shutdownHooks: shutdownHooks);
  } else if (error is ProcessExit) {
    // We've caught an exit code.
    if (error.immediate) {
      exit(error.exitCode);
      return error.exitCode;
    } else {
      return exitWithHooks(error.exitCode, shutdownHooks: shutdownHooks);
    }
  } else if (error is ProcessException &&
      _isErrorDueToGitMissing(error, globals.processManager, globals.logger)) {
    globals.printError('${error.message}\n');
    globals.printError(
      'An error was encountered when trying to run git.\n'
      "Please ensure git is installed and available in your system's search path. "
      'See https://docs.flutter.dev/get-started for instructions on '
      'installing git for your platform.',
    );
    return exitWithHooks(1, shutdownHooks: shutdownHooks);
  } else {
    // We've crashed; emit a log report.
    globals.stdio.stderrWrite('\n');
    if (!reportCrashes) {
      // Print the stack trace on the bots - don't write a crash report.
      globals.stdio.stderrWrite('$error\n');
      globals.stdio.stderrWrite('$stackTrace\n');

      final String featureFlagsEnabled = allConfigurableFeatures
          .where(featureFlags.isEnabled)
          .map((Feature f) => f.configSetting)
          .join(', ');
      globals.stdio.stderrWrite('Feature flags enabled: $featureFlagsEnabled\n');
      return exitWithHooks(1, shutdownHooks: shutdownHooks);
    }

    // Flutter tool crash analytics benefits from the concrete Dart error type.
    // The tool is not obfuscated, and collapsing unknown types to Object loses useful signal.
    // ignore: avoid_type_to_string
    globals.analytics.send(Event.exception(exception: error.runtimeType.toString()));

    if (!usingLocalEngine) {
      await asyncGuard(
        () async {
          final crashReportSender = CrashReportSender(
            platform: globals.platform,
            logger: globals.logger,
            operatingSystemUtils: globals.os,
            analytics: globals.analytics,
          );
          await crashReportSender.sendReport(
            error: error,
            stackTrace: stackTrace!,
            getFlutterVersion: getFlutterVersion,
            command: args.join(' '),
          );
        },
        onError: (dynamic error) {
          globals.printError('Error sending crash report: $error');
        },
      );
    }

    globals.printError('Oops; flutter has exited unexpectedly: "$error".');

    try {
      final logger = BufferLogger(
        terminal: globals.terminal,
        outputPreferences: globals.outputPreferences,
        verbose: true /* Capture flutter doctor -v */,
      );

      final doctorText = DoctorText(logger);

      final details = CrashDetails(
        command: _crashCommand(args),
        error: error,
        stackTrace: stackTrace!,
        doctorText: doctorText,
      );
      final File file = await _createLocalCrashReport(details);
      await globals.crashReporter!.informUser(details, file);

      return await exitWithHooks(1, shutdownHooks: shutdownHooks);
      // This catch catches all exceptions to ensure the message below is printed.
      // ignore: avoid_catches_without_on_clauses
    } catch (error, st) {
      globals.stdio.stderrWrite(
        'Unable to generate crash report due to secondary error: $error\n$st\n'
        '${globals.userMessages.flutterToolBugInstructions}\n',
      );
      // Any exception thrown here (including one thrown by `_exit()`) will
      // get caught by our zone's `onError` handler. In order to avoid an
      // infinite error loop, we throw an error that is recognized above
      // and will trigger an immediate exit.
      throw ProcessExit(1, immediate: true);
    }
  }
}

String _crashCommand(List<String> args) => 'flutter ${args.join(' ')}';

String _crashException(dynamic error) => '${error.runtimeType}: $error';

/// Saves the crash report to a local file.
Future<File> _createLocalCrashReport(CrashDetails details) async {
  final buffer = StringBuffer();

  buffer.writeln('Flutter crash report.');
  buffer.writeln('${globals.userMessages.flutterToolBugInstructions}\n');

  buffer.writeln('## command\n');
  buffer.writeln('${details.command}\n');

  buffer.writeln('## exception\n');
  buffer.writeln('${_crashException(details.error)}\n');
  buffer.writeln('```\n${details.stackTrace}```\n');

  buffer.writeln('## flutter doctor\n');
  buffer.writeln('```\n${await details.doctorText.text}```');

  late File crashFile;
  ErrorHandlingFileSystem.noExitOnFailure(() {
    try {
      crashFile = globals.fsUtils.getUniqueFile(globals.fs.currentDirectory, 'flutter', 'log');
      crashFile.writeAsStringSync(buffer.toString());
    } on FileSystemException catch (_) {
      // Fallback to the system temporary directory.
      try {
        crashFile = globals.fsUtils.getUniqueFile(globals.fs.systemTempDirectory, 'flutter', 'log');
        crashFile.writeAsStringSync(buffer.toString());
      } on FileSystemException catch (e) {
        globals.printError('Could not write crash report to disk: $e');
        globals.printError(buffer.toString());

        rethrow;
      }
    }
  });

  return crashFile;
}

bool _isErrorDueToGitMissing(
  ProcessException exception,
  ProcessManager processManager,
  Logger logger,
) {
  if (!exception.message.contains('git')) {
    return false;
  }

  try {
    return !processManager.canRun('git');
  } on Object catch (error) {
    logger.printTrace('Unable to check whether git is runnable: $error\n');
    return true;
  }
}
