// 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 'dart:io';

import 'package:file/memory.dart';
import 'package:flutter_tools/src/base/bot_detector.dart';
import 'package:flutter_tools/src/base/config.dart';
import 'package:flutter_tools/src/base/context.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/os.dart';
import 'package:flutter_tools/src/base/process.dart';
import 'package:flutter_tools/src/base/signals.dart';
import 'package:flutter_tools/src/base/terminal.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/context_runner.dart';
import 'package:flutter_tools/src/dart/pub.dart';
import 'package:flutter_tools/src/globals.dart' as globals;
import 'package:flutter_tools/src/persistent_tool_state.dart';
import 'package:flutter_tools/src/version.dart';
import 'package:unified_analytics/unified_analytics.dart';

import 'context.dart';
import 'fake_http_client.dart';
import 'fakes.dart';
import 'throwing_pub.dart';

export 'package:flutter_tools/src/base/context.dart' show Generator;

// A default value should be provided if the vast majority of tests should use
// this provider. For example, [BufferLogger], [MemoryFileSystem].
final _testbedDefaults = <Type, Generator>{
  // Keeps tests fast by avoiding the actual file system.
  FileSystem: () => MemoryFileSystem(
    style: globals.platform.isWindows ? FileSystemStyle.windows : FileSystemStyle.posix,
  ),
  ProcessManager: () => FakeProcessManager.any(),
  Logger: () => BufferLogger(
    terminal: AnsiTerminal(
      stdio: globals.stdio,
      platform: globals.platform,
    ), // Danger, using real stdio.
    outputPreferences: OutputPreferences.test(),
  ), // Allows reading logs and prevents stdout.
  OperatingSystemUtils: () => FakeOperatingSystemUtils(),
  OutputPreferences: () =>
      OutputPreferences.test(), // configures BufferLogger to avoid color codes.
  Analytics: () => const NoOpAnalytics(),
  FlutterVersion: () => FakeFlutterVersion(), // prevent requirement to mock git for test runner.
  Signals: () => FakeSignals(), // prevent registering actual signal handlers.
  Pub: () => const ThrowingPub(), // prevent accidental invocations of pub.
  BotDetector: () => const FakeBotDetector(true),
  Config: () => Config.test(
    name: Config.kFlutterSettings,
    directory: globals.fs.systemTempDirectory.createTempSync('flutter_config_dir_test.'),
    logger: globals.logger,
  ),
  PersistentToolState: () => PersistentToolState.test(
    directory: globals.fs.systemTempDirectory.createTempSync('flutter_config_dir_test.'),
    logger: globals.logger,
  ),
};

/// Manages interaction with the tool injection and runner system.
///
/// The Testbed automatically injects reasonable defaults through the context
/// DI system such as a [BufferLogger] and a [MemoryFileSystem].
///
/// Example:
///
/// Testing that a filesystem operation works as expected:
///
/// ```dart
/// void main() {
///   group('Example', () {
///     Testbed testbed;
///
///     setUp(() {
///       testbed = Testbed(setUp: () {
///         globals.fs.file('foo').createSync()
///       });
///     })
///
///     test('Can delete a file', () => testbed.run(() {
///       expect(globals.fs.file('foo').existsSync(), true);
///       globals.fs.file('foo').deleteSync();
///       expect(globals.fs.file('foo').existsSync(), false);
///     }));
///   });
/// }
/// ```
///
/// For a more detailed example, see the code in test_compiler_test.dart.
class TestBed {
  /// Creates a new [TestBed]
  ///
  /// `overrides` provides more overrides in addition to the test defaults.
  /// `setup` may be provided to apply mocks within the tool managed zone,
  /// including any specified overrides.
  TestBed({FutureOr<void> Function()? setup, Map<Type, Generator>? overrides})
    : _setup = setup,
      _overrides = overrides;

  final FutureOr<void> Function()? _setup;
  final Map<Type, Generator>? _overrides;

  /// Runs `test` within a tool zone.
  ///
  /// `overrides` may be used to provide new context values for the single test
  /// case or override any context values from the setup.
  Future<T?> run<T>(FutureOr<T> Function() test, {Map<Type, Generator>? overrides}) {
    final testOverrides = <Type, Generator>{
      ..._testbedDefaults,
      // Add the initial setUp overrides
      ...?_overrides,
      // Add the test-specific overrides
      ...?overrides,
    };
    if (testOverrides.containsKey(ProcessUtils)) {
      throw StateError('Do not inject ProcessUtils for testing, use ProcessManager instead.');
    }
    // Cache the original flutter root to restore after the test case.
    final String? originalFlutterRoot = Cache.flutterRoot;
    // Track pending timers to verify that they were correctly cleaned up.
    final timers = <Timer, StackTrace>{};

    return HttpOverrides.runZoned(() {
      return runInContext<T?>(() {
        return context.run<T?>(
          name: 'testbed-zone',
          zoneSpecification: ZoneSpecification(
            createTimer:
                (
                  Zone self,
                  ZoneDelegate parent,
                  Zone zone,
                  Duration duration,
                  void Function() timer,
                ) {
                  final Timer result = parent.createTimer(zone, duration, timer);
                  timers[result] = StackTrace.current;
                  return result;
                },
            createPeriodicTimer:
                (
                  Zone self,
                  ZoneDelegate parent,
                  Zone zone,
                  Duration period,
                  void Function(Timer) timer,
                ) {
                  final Timer result = parent.createPeriodicTimer(zone, period, timer);
                  timers[result] = StackTrace.current;
                  return result;
                },
          ),
          body: () async {
            Cache.flutterRoot = '';
            if (_setup != null) {
              await _setup.call();
            }
            await test();
            Cache.flutterRoot = originalFlutterRoot;
            for (final MapEntry<Timer, StackTrace> entry in timers.entries) {
              if (entry.key.isActive) {
                throw StateError('A Timer was active at the end of a test: ${entry.value}');
              }
            }
            return null;
          },
        );
      }, overrides: testOverrides);
    }, createHttpClient: (SecurityContext? c) => FakeHttpClient.any());
  }
}
