// 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:file/memory.dart';
import 'package:flutter_tools/runner.dart' as runner;
import 'package:flutter_tools/src/base/common.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart' as io;
import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/base/user_messages.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/globals.dart' as globals;
import 'package:flutter_tools/src/reporting/reporting.dart';
import 'package:flutter_tools/src/runner/flutter_command.dart';
import 'package:mockito/mockito.dart';

import '../../src/common.dart';
import '../../src/context.dart';

const String kCustomBugInstructions = 'These are instructions to report with a custom bug tracker.';

void main() {
  int firstExitCode;

  group('runner', () {
    setUp(() {
      // Instead of exiting with dart:io exit(), this causes an exception to
      // be thrown, which we catch with the onError callback in the zone below.
      //
      // Tests might trigger exit() multiple times.  In real life, exit() would
      // cause the VM to terminate immediately, so only the first one matters.
      firstExitCode = null;
      io.setExitFunctionForTests((int exitCode) {
        firstExitCode ??= exitCode;

        // TODO(jamesderlin): Ideally only the first call to exit() would be
        // honored and subsequent calls would be no-ops, but existing tests
        // rely on all calls to throw.
        throw 'test exit';
      });

      Cache.disableLocking();
    });

    tearDown(() {
      io.restoreExitFunction();
      Cache.enableLocking();
    });

    testUsingContext('error handling crash report (synchronous crash)', () async {
      final Completer<void> completer = Completer<void>();
      // runner.run() asynchronously calls the exit function set above, so we
      // catch it in a zone.
      unawaited(runZoned<Future<void>>(
        () {
          unawaited(runner.run(
            <String>['crash'],
            () => <FlutterCommand>[
              CrashingFlutterCommand(),
            ],
            // This flutterVersion disables crash reporting.
            flutterVersion: '[user-branch]/',
            reportCrashes: true,
          ));
          return null;
        },
        onError: (Object error, StackTrace stack) { // ignore: deprecated_member_use
          expect(firstExitCode, isNotNull);
          expect(firstExitCode, isNot(0));
          expect(error, 'test exit');
          completer.complete();
        },
      ));
      await completer.future;

      // This is the main check of this test.
      //
      // We are checking that, even though crash reporting failed with an
      // exception on the first attempt, the second attempt tries to report the
      // *original* crash, and not the crash from the first crash report
      // attempt.
      final CrashingUsage crashingUsage = globals.flutterUsage as CrashingUsage;
      expect(crashingUsage.sentException, 'an exception % --');
    }, overrides: <Type, Generator>{
      Platform: () => FakePlatform(environment: <String, String>{
        'FLUTTER_ANALYTICS_LOG_FILE': 'test',
        'FLUTTER_ROOT': '/',
      }),
      FileSystem: () => MemoryFileSystem(),
      ProcessManager: () => FakeProcessManager.any(),
      Usage: () => CrashingUsage(),
    });

    // This Completer completes when CrashingFlutterCommand.runCommand
    // completes, but ideally we'd want it to complete when execution resumes
    // runner.run.  Currently the distinction does not matter, but if it ever
    // does, this test might fail to catch a regression of
    // https://github.com/flutter/flutter/issues/56406.
    final Completer<void> commandCompleter = Completer<void>();
    testUsingContext('error handling crash report (asynchronous crash)', () async {
      final Completer<void> completer = Completer<void>();
      // runner.run() asynchronously calls the exit function set above, so we
      // catch it in a zone.
      unawaited(runZoned<Future<void>>(
        () {
          unawaited(runner.run(
            <String>['crash'],
            () => <FlutterCommand>[
              CrashingFlutterCommand(asyncCrash: true, completer: commandCompleter),
            ],
            // This flutterVersion disables crash reporting.
            flutterVersion: '[user-branch]/',
            reportCrashes: true,
          ));
          return null;
        },
        onError: (Object error, StackTrace stack) { // ignore: deprecated_member_use
          expect(firstExitCode, isNotNull);
          expect(firstExitCode, isNot(0));
          expect(error, 'test exit');
          completer.complete();
        },
      ));
      await completer.future;
    }, overrides: <Type, Generator>{
      Platform: () => FakePlatform(environment: <String, String>{
        'FLUTTER_ANALYTICS_LOG_FILE': 'test',
        'FLUTTER_ROOT': '/',
      }),
      FileSystem: () => MemoryFileSystem(),
      ProcessManager: () => FakeProcessManager.any(),

      CrashReporter: () => WaitingCrashReporter(commandCompleter.future),
    });

    testUsingContext('create local report', () async {
      final Completer<void> completer = Completer<void>();
      // runner.run() asynchronously calls the exit function set above, so we
      // catch it in a zone.
      unawaited(runZoned<Future<void>>(
        () {
        unawaited(runner.run(
          <String>['crash'],
          () => <FlutterCommand>[
            CrashingFlutterCommand(),
          ],
          // This flutterVersion disables crash reporting.
          flutterVersion: '[user-branch]/',
          reportCrashes: true,
        ));
        return null;
        },
        onError: (Object error, StackTrace stack) { // ignore: deprecated_member_use
          expect(firstExitCode, isNotNull);
          expect(firstExitCode, isNot(0));
          expect(error, 'test exit');
          completer.complete();
        },
      ));
      await completer.future;

      final String errorText = testLogger.errorText;
      expect(
        errorText,
        containsIgnoringWhitespace('Oops; flutter has exited unexpectedly: "an exception % --".\n'),
      );

      final File log = globals.fs.file('/flutter_01.log');
      final String logContents = log.readAsStringSync();
      expect(logContents, contains(kCustomBugInstructions));
      expect(logContents, contains('flutter crash'));
      expect(logContents, contains('String: an exception % --'));
      expect(logContents, contains('CrashingFlutterCommand.runCommand'));
      expect(logContents, contains('[✓] Flutter'));

      final VerificationResult argVerification = verify(globals.crashReporter.informUser(captureAny, any));
      final CrashDetails sentDetails = argVerification.captured.first as CrashDetails;
      expect(sentDetails.command, 'flutter crash');
      expect(sentDetails.error, 'an exception % --');
      expect(sentDetails.stackTrace.toString(), contains('CrashingFlutterCommand.runCommand'));
      expect(sentDetails.doctorText, contains('[✓] Flutter'));
    }, overrides: <Type, Generator>{
      Platform: () => FakePlatform(
        environment: <String, String>{
          'FLUTTER_ANALYTICS_LOG_FILE': 'test',
          'FLUTTER_ROOT': '/',
        },
        operatingSystem: 'linux'
      ),
      FileSystem: () => MemoryFileSystem(),
      ProcessManager: () => FakeProcessManager.any(),
      UserMessages: () => CustomBugInstructions(),
    });
  });
}

class CrashingFlutterCommand extends FlutterCommand {
  CrashingFlutterCommand({
    bool asyncCrash = false,
    Completer<void> completer,
  }) :  _asyncCrash = asyncCrash,
        _completer = completer;

  final bool _asyncCrash;
  final Completer<void> _completer;

  @override
  String get description => null;

  @override
  String get name => 'crash';

  @override
  Future<FlutterCommandResult> runCommand() async {
    const String error = 'an exception % --'; // Test URL encoding.
    if (!_asyncCrash) {
      throw error;
    }

    final Completer<void> completer = Completer<void>();
    Timer.run(() {
      completer.complete();
      throw error;
    });

    await completer.future;
    _completer.complete();

    return FlutterCommandResult.success();
  }
}

class CrashingUsage implements Usage {
  CrashingUsage() : _impl = Usage(
    versionOverride: '[user-branch]',
    runningOnBot: true,
  );

  final Usage _impl;

  dynamic get sentException => _sentException;
  dynamic _sentException;

  bool _firstAttempt = true;

  // Crash while crashing.
  @override
  void sendException(dynamic exception) {
    if (_firstAttempt) {
      _firstAttempt = false;
      throw 'CrashingUsage.sendException';
    }
    _sentException = exception;
  }

  @override
  bool get isFirstRun => _impl.isFirstRun;

  @override
  bool get suppressAnalytics => _impl.suppressAnalytics;

  @override
  set suppressAnalytics(bool value) {
    _impl.suppressAnalytics = value;
  }

  @override
  bool get enabled => _impl.enabled;

  @override
  set enabled(bool value) {
    _impl.enabled = value;
  }

  @override
  String get clientId => _impl.clientId;

  @override
  void sendCommand(String command, {Map<String, String> parameters}) =>
      _impl.sendCommand(command, parameters: parameters);

  @override
  void sendEvent(
    String category,
    String parameter, {
    String label,
    int value,
    Map<String, String> parameters,
  }) => _impl.sendEvent(
    category,
    parameter,
    label: label,
    value: value,
    parameters: parameters,
  );

  @override
  void sendTiming(
    String category,
    String variableName,
    Duration duration, {
    String label,
  }) => _impl.sendTiming(category, variableName, duration, label: label);

  @override
  Stream<Map<String, dynamic>> get onSend => _impl.onSend;

  @override
  Future<void> ensureAnalyticsSent() => _impl.ensureAnalyticsSent();

  @override
  void printWelcome() => _impl.printWelcome();
}

class CustomBugInstructions extends UserMessages {
  @override
  String get flutterToolBugInstructions => kCustomBugInstructions;
}

/// A fake [CrashReporter] that waits for a [Future] to complete.
///
/// Used to exacerbate a race between the success and failure paths of
/// [runner.run].  See https://github.com/flutter/flutter/issues/56406.
class WaitingCrashReporter implements CrashReporter {
  WaitingCrashReporter(Future<void> future) : _future = future;

  final Future<void> _future;

  @override
  Future<void> informUser(CrashDetails details, File crashFile) => _future;
}
