// 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 '../framework/devices.dart';
import '../framework/framework.dart';
import '../framework/talkback.dart' hide adbPath;
import '../framework/task_result.dart';
import '../framework/utils.dart';

TaskFunction createChannelsIntegrationTest({String? deviceIdOverride}) {
  return IntegrationTest(
    '${flutterDirectory.path}/dev/integration_tests/channels',
    'integration_test/main_test.dart',
    deviceIdOverride: deviceIdOverride,
  ).call;
}

TaskFunction createPlatformInteractionTest({String? deviceIdOverride}) {
  return DriverTest(
    '${flutterDirectory.path}/dev/integration_tests/platform_interaction',
    'lib/main.dart',
    deviceIdOverride: deviceIdOverride,
  ).call;
}

TaskFunction createFlavorsTest({
  Map<String, String>? environment,
  List<String>? extraOptions,
  String? deviceIdOverride,
}) {
  return DriverTest(
    '${flutterDirectory.path}/dev/integration_tests/flavors',
    'lib/main.dart',
    extraOptions: extraOptions ?? <String>['--flavor', 'paid'],
    environment: environment,
    deviceIdOverride: deviceIdOverride,
  ).call;
}

TaskFunction createIntegrationTestFlavorsTest({
  Map<String, String>? environment,
  String? deviceIdOverride,
}) {
  return IntegrationTest(
    '${flutterDirectory.path}/dev/integration_tests/flavors',
    'integration_test/integration_test.dart',
    extraOptions: <String>['--flavor', 'paid'],
    environment: environment,
    deviceIdOverride: deviceIdOverride,
  ).call;
}

TaskFunction createExternalTexturesFrameRateIntegrationTest({
  List<String> extraOptions = const <String>[],
  String? deviceIdOverride,
}) {
  return DriverTest(
    '${flutterDirectory.path}/dev/integration_tests/external_textures',
    'lib/frame_rate_main.dart',
    extraOptions: extraOptions,
    deviceIdOverride: deviceIdOverride,
  ).call;
}

TaskFunction createPlatformChannelSampleTest({String? deviceIdOverride}) {
  return DriverTest(
    '${flutterDirectory.path}/examples/platform_channel',
    'test_driver/button_tap.dart',
    deviceIdOverride: deviceIdOverride,
  ).call;
}

TaskFunction createPlatformChannelSwiftSampleTest({String? deviceIdOverride}) {
  return DriverTest(
    '${flutterDirectory.path}/examples/platform_channel_swift',
    'test_driver/button_tap.dart',
    deviceIdOverride: deviceIdOverride,
  ).call;
}

TaskFunction createHybridAndroidViewsIntegrationTest() {
  return DriverTest(
    '${flutterDirectory.path}/dev/integration_tests/hybrid_android_views',
    'lib/main.dart',
  ).call;
}

TaskFunction createAndroidSemanticsIntegrationTest() {
  return IntegrationTest(
    '${flutterDirectory.path}/dev/integration_tests/android_semantics_testing',
    'integration_test/main_test.dart',
    withTalkBack: true,
  ).call;
}

TaskFunction createEndToEndKeyboardTest({String? deviceIdOverride}) {
  return DriverTest(
    '${flutterDirectory.path}/dev/integration_tests/ui',
    'lib/keyboard_resize.dart',
    deviceIdOverride: deviceIdOverride,
  ).call;
}

TaskFunction createEndToEndFrameNumberTest({String? deviceIdOverride}) {
  return DriverTest(
    '${flutterDirectory.path}/dev/integration_tests/ui',
    'lib/frame_number.dart',
    deviceIdOverride: deviceIdOverride,
  ).call;
}

TaskFunction createEndToEndDriverTest({
  Map<String, String>? environment,
  String? deviceIdOverride,
}) {
  return DriverTest(
    '${flutterDirectory.path}/dev/integration_tests/ui',
    'lib/driver.dart',
    environment: environment,
    deviceIdOverride: deviceIdOverride,
  ).call;
}

TaskFunction createEndToEndKeyboardTextfieldTest({String? deviceIdOverride}) {
  return DriverTest(
    '${flutterDirectory.path}/dev/integration_tests/ui',
    'lib/keyboard_textfield.dart',
    deviceIdOverride: deviceIdOverride,
  ).call;
}

TaskFunction createSolidColorTest({required bool enableImpeller}) {
  return DriverTest(
    '${flutterDirectory.path}/dev/integration_tests/ui',
    'lib/solid_color.dart',
    extraOptions: <String>[if (enableImpeller) '--enable-impeller'],
  ).call;
}

TaskFunction createTextureTest({required bool enableImpeller}) {
  return DriverTest(
    '${flutterDirectory.path}/examples/texture',
    'test_driver/texture_test.dart',
    extraOptions: <String>[if (enableImpeller) '--enable-impeller'],
  ).call;
}

TaskFunction androidVerifiedInputTest({Map<String, String>? environment}) {
  return DriverTest(
    '${flutterDirectory.path}/dev/integration_tests/android_verified_input',
    'lib/main.dart',
    environment: environment,
  ).call;
}

// Can run on emulator or physical android device.
// Device must have developer settings enabled.
// Device must be android api 30 or higher.
TaskFunction createDisplayCutoutTest() {
  return IntegrationTest(
    '${flutterDirectory.path}/dev/integration_tests/display_cutout_rotation/',
    'integration_test/display_cutout_test.dart',
    setup: (Device device) async {
      if (device is! AndroidDevice) {
        // Only android devices support this cutoutTest.
        throw TaskResult.failure('This test should only target android');
      }
      // Test requires developer settings added in 28 and behavior added in 30.
      final String sdkResult = await device.shellEval('getprop', <String>['ro.build.version.sdk']);
      if (sdkResult.startsWith('2') || sdkResult.startsWith('1') || sdkResult.length == 1) {
        throw TaskResult.failure('This test should only target android 30+.');
      }
      print('Adding Synthetic notch...');
      // This command will cause any running android activity to be recreated.
      await device.shellExec('cmd', <String>[
        'overlay',
        'enable',
        'com.android.internal.display.cutout.emulation.tall',
      ]);
    },
    tearDown: (Device device) async {
      if (device is AndroidDevice) {
        print('Removing Synthetic notch...');
        await device.shellExec('cmd', <String>[
          'overlay',
          'disable',
          'com.android.internal.display.cutout.emulation.tall',
        ]);
      }
    },
  ).call;
}

TaskFunction dartDefinesTask({String? deviceIdOverride}) {
  return DriverTest(
    '${flutterDirectory.path}/dev/integration_tests/ui',
    'lib/defines.dart',
    deviceIdOverride: deviceIdOverride,
    extraOptions: <String>[
      '--dart-define=test.valueA=Example,A',
      '--dart-define=test.valueB=Value',
    ],
  ).call;
}

TaskFunction featureFlagsTask() {
  return () async {
    await flutter('config', options: const <String>['--enable-windowing']);

    return DriverTest(
      '${flutterDirectory.path}/dev/integration_tests/ui',
      'lib/feature_flags.dart',
    ).call();
  };
}

TaskFunction createEndToEndIntegrationTest({String? deviceIdOverride}) {
  return IntegrationTest(
    '${flutterDirectory.path}/dev/integration_tests/ui',
    'integration_test/integration_test.dart',
    deviceIdOverride: deviceIdOverride,
  ).call;
}

TaskFunction createSpellCheckIntegrationTest({String? deviceIdOverride}) {
  return IntegrationTest(
    '${flutterDirectory.path}/dev/integration_tests/spell_check',
    'integration_test/integration_test.dart',
    deviceIdOverride: deviceIdOverride,
  ).call;
}

TaskFunction createWindowsStartupDriverTest({String? deviceIdOverride}) {
  return DriverTest(
    '${flutterDirectory.path}/dev/integration_tests/windows_startup_test',
    'lib/main.dart',
    deviceIdOverride: deviceIdOverride,
  ).call;
}

TaskFunction createEngineIntegrationGoldenTest() {
  return IntegrationTest(
    '${flutterDirectory.path}/dev/integration_tests/engine_integration_golden_test',
    'integration_test/engine_integration_golden_test.dart',
    createPlatforms: <String>['windows'],
  ).call;
}

TaskFunction createWindowingDriverTest() {
  return () async {
    await flutter('config', options: const <String>['--enable-windowing']);
    return DriverTest(
      '${flutterDirectory.path}/dev/integration_tests/windowing_test',
      'lib/main.dart',
    ).call();
  };
}

TaskFunction createWideGamutTest() {
  return IntegrationTest(
    '${flutterDirectory.path}/dev/integration_tests/wide_gamut_test',
    'integration_test/app_test.dart',
    createPlatforms: <String>['ios', 'macos'],
  ).call;
}

class DriverTest {
  DriverTest(
    this.testDirectory,
    this.testTarget, {
    this.extraOptions = const <String>[],
    this.deviceIdOverride,
    this.environment,
  });

  final String testDirectory;
  final String testTarget;
  final List<String> extraOptions;
  final String? deviceIdOverride;
  final Map<String, String>? environment;

  Future<TaskResult> call() {
    return inDirectory<TaskResult>(testDirectory, () async {
      String deviceId;
      Device? selectedDevice;
      if (deviceIdOverride != null) {
        deviceId = deviceIdOverride!;
      } else {
        selectedDevice = await devices.workingDevice;
        await selectedDevice.unlock();
        deviceId = selectedDevice.deviceId;
      }
      await flutter('packages', options: <String>['get']);

      final bool isAndroidRun = selectedDevice != null
          ? selectedDevice is AndroidDevice
          : const <DeviceOperatingSystem>{
              DeviceOperatingSystem.android,
              DeviceOperatingSystem.androidArm,
              DeviceOperatingSystem.androidArm64,
            }.contains(deviceOperatingSystem);

      String? devicelabAdbPath;
      if (isAndroidRun) {
        try {
          devicelabAdbPath = adbPath;
        } on DeviceException {
          devicelabAdbPath = null;
        }
      }
      // Make the device ID available in the driver code, so tools like ADB can
      // reference it if needed.
      final env = <String, String>{
        ...?environment,
        'FLUTTER_DEVICE_ID_NUMBER': deviceId,
        'FLUTTER_ADB_PATH': ?devicelabAdbPath,
      };

      final options = <String>[
        '--no-android-gradle-daemon',
        '-v',
        '-t',
        testTarget,
        '-d',
        deviceId,
        ...extraOptions,
      ];
      await flutter('drive', options: options, environment: env);
      return TaskResult.success(null);
    });
  }
}

class IntegrationTest {
  IntegrationTest(
    this.testDirectory,
    this.testTarget, {
    this.extraOptions = const <String>[],
    this.createPlatforms = const <String>[],
    this.withTalkBack = false,
    this.environment,
    this.setup,
    this.tearDown,
    this.deviceIdOverride,
  });

  final String testDirectory;
  final String testTarget;
  final List<String> extraOptions;
  final List<String> createPlatforms;
  final bool withTalkBack;
  final Map<String, String>? environment;
  final String? deviceIdOverride;

  /// Run before flutter drive with the result from devices.workingDevice.
  final Future<void> Function(Device device)? setup;

  /// Run after flutter drive with the result from devices.workingDevice.
  final Future<void> Function(Device device)? tearDown;

  Future<TaskResult> call() {
    return inDirectory<TaskResult>(testDirectory, () async {
      String deviceId;
      Device? selectedDevice;
      if (deviceIdOverride != null) {
        deviceId = deviceIdOverride!;
      } else {
        selectedDevice = await devices.workingDevice;
        await selectedDevice.unlock();
        deviceId = selectedDevice.deviceId;
      }
      await flutter('packages', options: <String>['get']);
      await setup?.call(await devices.workingDevice);

      if (createPlatforms.isNotEmpty) {
        await flutter(
          'create',
          options: <String>['--platforms', createPlatforms.join(','), '--no-overwrite', '.'],
        );
      }

      if (withTalkBack) {
        if (selectedDevice is! AndroidDevice) {
          return TaskResult.failure(
            'A test that enables TalkBack can only be run on Android devices',
          );
        }
        await enableTalkBack();
      }

      final options = <String>['-v', '-d', deviceId, testTarget, ...extraOptions];
      await flutter('test', options: options, environment: environment);
      await tearDown?.call(await devices.workingDevice);

      if (withTalkBack) {
        await disableTalkBack();
      }

      return TaskResult.success(null);
    });
  }
}
