// 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.

// @dart = 2.8

import 'dart:async';

import 'package:file/file.dart';
import 'package:file/memory.dart';
import 'package:file_testing/file_testing.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/build_system/build_system.dart';
import 'package:flutter_tools/src/bundle.dart';
import 'package:flutter_tools/src/bundle_builder.dart';
import 'package:flutter_tools/src/convert.dart';
import 'package:flutter_tools/src/custom_devices/custom_device.dart';
import 'package:flutter_tools/src/custom_devices/custom_device_config.dart';
import 'package:flutter_tools/src/custom_devices/custom_devices_config.dart';
import 'package:flutter_tools/src/device.dart';
import 'package:flutter_tools/src/globals.dart' as globals;
import 'package:flutter_tools/src/linux/application_package.dart';
import 'package:flutter_tools/src/project.dart';
import 'package:meta/meta.dart';
import 'package:test/fake.dart';

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


void _writeCustomDevicesConfigFile(Directory dir, List<CustomDeviceConfig> configs) {
  dir.createSync();

  final File file = dir.childFile('.flutter_custom_devices.json');
  file.writeAsStringSync(jsonEncode(
    <String, dynamic>{
      'custom-devices': configs.map<dynamic>((CustomDeviceConfig c) => c.toJson()).toList()
    }
  ));
}

FlutterProject _setUpFlutterProject(Directory directory) {
  final FlutterProjectFactory flutterProjectFactory = FlutterProjectFactory(
    fileSystem: directory.fileSystem,
    logger: BufferLogger.test(),
  );
  return flutterProjectFactory.fromDirectory(directory);
}

void main() {
  testWithoutContext('replacing string interpolation occurrences in custom device commands', () async {
    expect(
      interpolateCommand(
        <String>['scp', r'${localPath}', r'/tmp/${appName}', 'pi@raspberrypi'],
        <String, String>{
          'localPath': 'build/flutter_assets',
          'appName': 'hello_world'
        }
      ),
      <String>[
        'scp', 'build/flutter_assets', '/tmp/hello_world', 'pi@raspberrypi'
      ]
    );

    expect(
      interpolateCommand(
        <String>[r'${test1}', r' ${test2}', r'${test3}'],
        <String, String>{
          'test1': '_test1',
          'test2': '_test2'
        }
      ),
      <String>[
        '_test1', ' _test2', r''
      ]
    );

    expect(
      interpolateCommand(
        <String>[r'${test1}', r' ${test2}', r'${test3}'],
        <String, String>{
          'test1': '_test1',
          'test2': '_test2'
        },
        additionalReplacementValues: <String, String>{
          'test2': '_nottest2',
          'test3': '_test3'
        }
      ),
      <String>[
        '_test1', ' _test2', r'_test3'
      ]
    );
  });

  final CustomDeviceConfig testConfig = CustomDeviceConfig(
    id: 'testid',
    label: 'testlabel',
    sdkNameAndVersion: 'testsdknameandversion',
    enabled: true,
    pingCommand: const <String>['testping'],
    pingSuccessRegex: RegExp('testpingsuccess'),
    postBuildCommand: const <String>['testpostbuild'],
    installCommand: const <String>['testinstall'],
    uninstallCommand: const <String>['testuninstall'],
    runDebugCommand: const <String>['testrundebug'],
    forwardPortCommand: const <String>['testforwardport'],
    forwardPortSuccessRegex: RegExp('testforwardportsuccess'),
    screenshotCommand: const <String>['testscreenshot']
  );

  const String testConfigPingSuccessOutput = 'testpingsuccess\n';
  const String testConfigForwardPortSuccessOutput = 'testforwardportsuccess\n';
  final CustomDeviceConfig disabledTestConfig = testConfig.copyWith(enabled: false);
  final CustomDeviceConfig testConfigNonForwarding = testConfig.copyWith(
    explicitForwardPortCommand: true,
    forwardPortCommand: null,
    explicitForwardPortSuccessRegex: true,
    forwardPortSuccessRegex: null,
  );

  testUsingContext('CustomDevice defaults',
    () async {
      final CustomDevice device = CustomDevice(
        config: testConfig,
        processManager: FakeProcessManager.any(),
        logger: BufferLogger.test()
      );

      final PrebuiltLinuxApp linuxApp = PrebuiltLinuxApp(executable: 'foo');

      expect(device.id, 'testid');
      expect(device.name, 'testlabel');
      expect(device.platformType, PlatformType.custom);
      expect(await device.sdkNameAndVersion, 'testsdknameandversion');
      expect(await device.targetPlatform, TargetPlatform.linux_arm64);
      expect(await device.installApp(linuxApp), true);
      expect(await device.uninstallApp(linuxApp), true);
      expect(await device.isLatestBuildInstalled(linuxApp), false);
      expect(await device.isAppInstalled(linuxApp), false);
      expect(await device.stopApp(linuxApp), false);
      expect(device.category, Category.mobile);

      expect(device.supportsRuntimeMode(BuildMode.debug), true);
      expect(device.supportsRuntimeMode(BuildMode.profile), false);
      expect(device.supportsRuntimeMode(BuildMode.release), false);
      expect(device.supportsRuntimeMode(BuildMode.jitRelease), false);
    },
    overrides: <Type, dynamic Function()>{
      FileSystem: () => MemoryFileSystem.test(),
      ProcessManager: () => FakeProcessManager.any()
    }
  );

  testWithoutContext('CustomDevice: no devices listed if only disabled devices configured', () async {
    final MemoryFileSystem fs = MemoryFileSystem.test();
    final Directory dir = fs.directory('custom_devices_config_dir');

    _writeCustomDevicesConfigFile(dir, <CustomDeviceConfig>[disabledTestConfig]);

    expect(await CustomDevices(
      featureFlags: TestFeatureFlags(areCustomDevicesEnabled: true),
      logger: BufferLogger.test(),
      processManager: FakeProcessManager.any(),
      config: CustomDevicesConfig.test(
        fileSystem: fs,
        directory: dir,
        logger: BufferLogger.test()
      )
    ).devices, <Device>[]);
  });

  testWithoutContext('CustomDevice: no devices listed if custom devices feature flag disabled', () async {
    final MemoryFileSystem fs = MemoryFileSystem.test();
    final Directory dir = fs.directory('custom_devices_config_dir');

    _writeCustomDevicesConfigFile(dir, <CustomDeviceConfig>[testConfig]);

    expect(await CustomDevices(
      featureFlags: TestFeatureFlags(),
      logger: BufferLogger.test(),
      processManager: FakeProcessManager.any(),
      config: CustomDevicesConfig.test(
        fileSystem: fs,
        directory: dir,
        logger: BufferLogger.test()
      )
    ).devices, <Device>[]);
  });

  testWithoutContext('CustomDevices.devices', () async {
    final MemoryFileSystem fs = MemoryFileSystem.test();
    final Directory dir = fs.directory('custom_devices_config_dir');

    _writeCustomDevicesConfigFile(dir, <CustomDeviceConfig>[testConfig]);

    expect(
      await CustomDevices(
        featureFlags: TestFeatureFlags(areCustomDevicesEnabled: true),
        logger: BufferLogger.test(),
        processManager: FakeProcessManager.list(<FakeCommand>[
          FakeCommand(
            command: testConfig.pingCommand,
            stdout: testConfigPingSuccessOutput
          ),
        ]),
        config: CustomDevicesConfig.test(
          fileSystem: fs,
          directory: dir,
          logger: BufferLogger.test()
        )
      ).devices,
      hasLength(1)
    );
  });

  testWithoutContext('CustomDevices.discoverDevices successfully discovers devices and executes ping command', () async {
    final MemoryFileSystem fs = MemoryFileSystem.test();
    final Directory dir = fs.directory('custom_devices_config_dir');

    _writeCustomDevicesConfigFile(dir, <CustomDeviceConfig>[testConfig]);

    bool pingCommandWasExecuted = false;

    final CustomDevices discovery = CustomDevices(
      featureFlags: TestFeatureFlags(areCustomDevicesEnabled: true),
      logger: BufferLogger.test(),
      processManager: FakeProcessManager.list(<FakeCommand>[
        FakeCommand(
          command: testConfig.pingCommand,
          onRun: () => pingCommandWasExecuted = true,
          stdout: testConfigPingSuccessOutput
        ),
      ]),
      config: CustomDevicesConfig.test(
        fileSystem: fs,
        directory: dir,
        logger: BufferLogger.test(),
      ),
    );

    final List<Device> discoveredDevices = await discovery.discoverDevices();

    expect(discoveredDevices, hasLength(1));
    expect(pingCommandWasExecuted, true);
  });

  testWithoutContext("CustomDevices.discoverDevices doesn't report device when ping command fails", () async {
    final MemoryFileSystem fs = MemoryFileSystem.test();
    final Directory dir = fs.directory('custom_devices_config_dir');

    _writeCustomDevicesConfigFile(dir, <CustomDeviceConfig>[testConfig]);

    final CustomDevices discovery = CustomDevices(
      featureFlags: TestFeatureFlags(areCustomDevicesEnabled: true),
      logger: BufferLogger.test(),
      processManager: FakeProcessManager.list(<FakeCommand>[
        FakeCommand(
          command: testConfig.pingCommand,
          stdout: testConfigPingSuccessOutput,
          exitCode: 1
        ),
      ]),
      config: CustomDevicesConfig.test(
        fileSystem: fs,
        directory: dir,
        logger: BufferLogger.test(),
      ),
    );

    expect(await discovery.discoverDevices(), hasLength(0));
  });

  testWithoutContext("CustomDevices.discoverDevices doesn't report device when ping command output doesn't match ping success regex", () async {
    final MemoryFileSystem fs = MemoryFileSystem.test();
    final Directory dir = fs.directory('custom_devices_config_dir');

    _writeCustomDevicesConfigFile(dir, <CustomDeviceConfig>[testConfig]);

    final CustomDevices discovery = CustomDevices(
      featureFlags: TestFeatureFlags(areCustomDevicesEnabled: true),
      logger: BufferLogger.test(),
      processManager: FakeProcessManager.list(<FakeCommand>[
        FakeCommand(
          command: testConfig.pingCommand,
        ),
      ]),
      config: CustomDevicesConfig.test(
        fileSystem: fs,
        directory: dir,
        logger: BufferLogger.test(),
      ),
    );

    expect(await discovery.discoverDevices(), hasLength(0));
  });

  testWithoutContext('CustomDevice.isSupportedForProject is true with editable host app', () async {
    final MemoryFileSystem fileSystem = MemoryFileSystem.test();
    fileSystem.file('pubspec.yaml').createSync();
    fileSystem.file('.packages').createSync();

    final FlutterProject flutterProject = _setUpFlutterProject(fileSystem.currentDirectory);

    expect(CustomDevice(
      config: testConfig,
      logger: BufferLogger.test(),
      processManager: FakeProcessManager.any(),
    ).isSupportedForProject(flutterProject), true);
  });

  testUsingContext(
    'CustomDevice.install invokes uninstall and install command',
    () async {
      bool bothCommandsWereExecuted = false;

      final CustomDevice device = CustomDevice(
          config: testConfig,
          logger: BufferLogger.test(),
          processManager: FakeProcessManager.list(<FakeCommand>[
            FakeCommand(command: testConfig.uninstallCommand),
            FakeCommand(command: testConfig.installCommand, onRun: () => bothCommandsWereExecuted = true)
          ])
      );

      expect(await device.installApp(PrebuiltLinuxApp(executable: 'exe')), true);
      expect(bothCommandsWereExecuted, true);
    },
    overrides: <Type, dynamic Function()>{
      FileSystem: () => MemoryFileSystem.test(),
      ProcessManager: () => FakeProcessManager.any()
    }
  );

  testWithoutContext('CustomDevicePortForwarder will run and terminate forwardPort command', () async {
    final Completer<void> forwardPortCommandCompleter = Completer<void>();

    final CustomDevicePortForwarder forwarder = CustomDevicePortForwarder(
      deviceName: 'testdevicename',
      forwardPortCommand: testConfig.forwardPortCommand,
      forwardPortSuccessRegex: testConfig.forwardPortSuccessRegex,
      logger: BufferLogger.test(),
      processManager: FakeProcessManager.list(<FakeCommand>[
        FakeCommand(
          command: testConfig.forwardPortCommand,
          stdout: testConfigForwardPortSuccessOutput,
          completer: forwardPortCommandCompleter
        )
      ])
    );

    // this should start the command
    expect(await forwarder.forward(12345), 12345);
    expect(forwardPortCommandCompleter.isCompleted, false);

    // this should terminate it
    await forwarder.dispose();

    // the termination should have completed our completer
    expect(forwardPortCommandCompleter.isCompleted, true);
  });

  testWithoutContext('CustomDevice forwards observatory port correctly when port forwarding is configured', () async {
    final Completer<void> runDebugCompleter = Completer<void>();
    final Completer<void> forwardPortCompleter = Completer<void>();

    final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
      FakeCommand(
        command: testConfig.runDebugCommand,
        completer: runDebugCompleter,
        stdout: 'The Dart VM service is listening on http://127.0.0.1:12345/abcd/\n',
      ),
      FakeCommand(
        command: testConfig.forwardPortCommand,
        completer: forwardPortCompleter,
        stdout: testConfigForwardPortSuccessOutput,
      )
    ]);

    final CustomDeviceAppSession appSession = CustomDeviceAppSession(
      name: 'testname',
      device: CustomDevice(
        config: testConfig,
        logger: BufferLogger.test(),
        processManager: processManager
      ),
      appPackage: PrebuiltLinuxApp(executable: 'testexecutable'),
      logger: BufferLogger.test(),
      processManager: processManager,
    );

    final LaunchResult launchResult = await appSession.start(debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug));

    expect(launchResult.started, true);
    expect(launchResult.observatoryUri, Uri.parse('http://127.0.0.1:12345/abcd/'));
    expect(runDebugCompleter.isCompleted, false);
    expect(forwardPortCompleter.isCompleted, false);

    expect(await appSession.stop(), true);
    expect(runDebugCompleter.isCompleted, true);
    expect(forwardPortCompleter.isCompleted, true);
  });

  testWithoutContext('CustomDeviceAppSession forwards observatory port correctly when port forwarding is not configured', () async {
    final Completer<void> runDebugCompleter = Completer<void>();

    final FakeProcessManager processManager = FakeProcessManager.list(
      <FakeCommand>[
        FakeCommand(
          command: testConfigNonForwarding.runDebugCommand,
          completer: runDebugCompleter,
          stdout: 'The Dart VM service is listening on http://192.168.178.123:12345/abcd/\n'
        ),
      ]
    );

    final CustomDeviceAppSession appSession = CustomDeviceAppSession(
      name: 'testname',
      device: CustomDevice(
        config: testConfigNonForwarding,
        logger: BufferLogger.test(),
        processManager: processManager
      ),
      appPackage: PrebuiltLinuxApp(executable: 'testexecutable'),
      logger: BufferLogger.test(),
      processManager: processManager
    );

    final LaunchResult launchResult = await appSession.start(debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug));

    expect(launchResult.started, true);
    expect(launchResult.observatoryUri, Uri.parse('http://192.168.178.123:12345/abcd/'));
    expect(runDebugCompleter.isCompleted, false);

    expect(await appSession.stop(), true);
    expect(runDebugCompleter.isCompleted, true);
  });

  testUsingContext(
    'custom device end-to-end test',
    () async {
      final Completer<void> runDebugCompleter = Completer<void>();
      final Completer<void> forwardPortCompleter = Completer<void>();

      final FakeProcessManager processManager = FakeProcessManager.list(
        <FakeCommand>[
          FakeCommand(
            command: testConfig.pingCommand,
            stdout: testConfigPingSuccessOutput
          ),
          FakeCommand(command: testConfig.postBuildCommand),
          FakeCommand(command: testConfig.uninstallCommand),
          FakeCommand(command: testConfig.installCommand),
          FakeCommand(
            command: testConfig.runDebugCommand,
            completer: runDebugCompleter,
            stdout: 'The Dart VM service is listening on http://127.0.0.1:12345/abcd/\n',
          ),
          FakeCommand(
            command: testConfig.forwardPortCommand,
            completer: forwardPortCompleter,
            stdout: testConfigForwardPortSuccessOutput
          )
        ]
      );

      // Reuse our filesystem from context instead of mixing two filesystem instances
      // together
      final FileSystem fs = globals.fs;

      // CustomDevice.startApp doesn't care whether we pass a prebuilt app or
      // buildable app as long as we pass prebuiltApplication as false
      final PrebuiltLinuxApp app = PrebuiltLinuxApp(executable: 'testexecutable');

      final Directory configFileDir = fs.directory('custom_devices_config_dir');
      _writeCustomDevicesConfigFile(configFileDir, <CustomDeviceConfig>[testConfig]);

      // finally start actually testing things
      final CustomDevices customDevices = CustomDevices(
        featureFlags: TestFeatureFlags(areCustomDevicesEnabled: true),
        processManager: processManager,
        logger: BufferLogger.test(),
        config: CustomDevicesConfig.test(
          fileSystem: fs,
          directory: configFileDir,
          logger: BufferLogger.test()
        )
      );

      final List<Device> devices = await customDevices.discoverDevices();
      expect(devices.length, 1);
      expect(devices.single, isA<CustomDevice>());

      final CustomDevice device = devices.single as CustomDevice;
      expect(device.id, testConfig.id);
      expect(device.name, testConfig.label);
      expect(await device.sdkNameAndVersion, testConfig.sdkNameAndVersion);

      final LaunchResult result = await device.startApp(
        app,
        debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
        bundleBuilder: FakeBundleBuilder()
      );
      expect(result.started, true);
      expect(result.hasObservatory, true);
      expect(result.observatoryUri, Uri.tryParse('http://127.0.0.1:12345/abcd/'));
      expect(runDebugCompleter.isCompleted, false);
      expect(forwardPortCompleter.isCompleted, false);

      expect(await device.stopApp(app), true);
      expect(runDebugCompleter.isCompleted, true);
      expect(forwardPortCompleter.isCompleted, true);
    },
    overrides: <Type, Generator>{
      FileSystem: () => MemoryFileSystem.test(),
      ProcessManager: () => FakeProcessManager.any()
    }
  );

  testWithoutContext('CustomDevice screenshotting', () async {
    bool screenshotCommandWasExecuted = false;

    final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
      FakeCommand(
        command: testConfig.screenshotCommand,
        onRun: () => screenshotCommandWasExecuted = true,
      )
    ]);

    final MemoryFileSystem fs = MemoryFileSystem.test();
    final File screenshotFile = fs.file('screenshot.png');

    final CustomDevice device = CustomDevice(
      config: testConfig,
      logger: BufferLogger.test(),
      processManager: processManager
    );

    expect(device.supportsScreenshot, true);

    await device.takeScreenshot(screenshotFile);
    expect(screenshotCommandWasExecuted, true);
    expect(screenshotFile, exists);
  });

  testWithoutContext('CustomDevice without screenshotting support', () async {
    bool screenshotCommandWasExecuted = false;

    final FakeProcessManager processManager = FakeProcessManager.list(<FakeCommand>[
      FakeCommand(
        command: testConfig.screenshotCommand,
        onRun: () => screenshotCommandWasExecuted = true,
      )
    ]);

    final MemoryFileSystem fs = MemoryFileSystem.test();
    final File screenshotFile = fs.file('screenshot.png');

    final CustomDevice device = CustomDevice(
        config: testConfig.copyWith(
          explicitScreenshotCommand: true,
          screenshotCommand: null
        ),
        logger: BufferLogger.test(),
        processManager: processManager
    );

    expect(device.supportsScreenshot, false);
    expect(
      () => device.takeScreenshot(screenshotFile),
      throwsA(const TypeMatcher<UnsupportedError>()),
    );
    expect(screenshotCommandWasExecuted, false);
    expect(screenshotFile.existsSync(), false);
  });

  testWithoutContext('CustomDevice returns correct target platform', () async {
    final CustomDevice device = CustomDevice(
      config: testConfig.copyWith(
        platform: TargetPlatform.linux_x64
      ),
      logger: BufferLogger.test(),
      processManager: FakeProcessManager.empty()
    );

    expect(await device.targetPlatform, TargetPlatform.linux_x64);
  });

  testWithoutContext('CustomDeviceLogReader cancels subscriptions before closing logLines stream', () async {
    final CustomDeviceLogReader logReader = CustomDeviceLogReader('testname');

    final Iterable<List<int>> lines = Iterable<List<int>>.generate(5, (int _) => utf8.encode('test'));

    logReader.listenToProcessOutput(
      FakeProcess(
        exitCode: Future<int>.value(0),
        stdout: Stream<List<int>>.fromIterable(lines),
        stderr: Stream<List<int>>.fromIterable(lines),
      ),
    );

    final List<MyFakeStreamSubscription<String>> subscriptions = <MyFakeStreamSubscription<String>>[];
    bool logLinesStreamDone = false;
    logReader.logLines.listen((_) {}, onDone: () {
      expect(subscriptions, everyElement((MyFakeStreamSubscription<String> s) => s.canceled));
      logLinesStreamDone = true;
    });

    logReader.subscriptions.replaceRange(
      0,
      logReader.subscriptions.length,
      logReader.subscriptions.map(
        (StreamSubscription<String> e) => MyFakeStreamSubscription<String>(e)
      ),
    );

    subscriptions.addAll(logReader.subscriptions.cast());

    await logReader.dispose();

    expect(logLinesStreamDone, true);
  });
}

class MyFakeStreamSubscription<T> extends Fake implements StreamSubscription<T> {
  MyFakeStreamSubscription(this.parent);

  StreamSubscription<T> parent;
  bool canceled = false;

  @override
  Future<void> cancel() {
    canceled = true;
    return parent.cancel();
  }
}

class FakeBundleBuilder extends Fake implements BundleBuilder {
  @override
  Future<void> build({
    TargetPlatform platform,
    BuildInfo buildInfo,
    FlutterProject project,
    String mainPath,
    String manifestPath = defaultManifestPath,
    String applicationKernelFilePath,
    String depfilePath,
    String assetDirPath,
    @visibleForTesting BuildSystem buildSystem
  }) async {}
}
