// Copyright 2013 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:convert';
import 'dart:io' as io;

import 'package:file/file.dart';
import 'package:path/path.dart' as p;

import 'common.dart';

const String _kiOSDestination = 'ios-destination';
const String _kSkip = 'skip';
const String _kXcodeBuildCommand = 'xcodebuild';
const String _kXCRunCommand = 'xcrun';
const String _kFoundNoSimulatorsMessage =
    'Cannot find any available simulators, tests failed';

/// The command to run iOS XCTests in plugins, this should work for both XCUnitTest and XCUITest targets.
/// The tests target have to be added to the xcode project of the example app. Usually at "example/ios/Runner.xcworkspace".
/// The static analyzer is also run.
class XCTestCommand extends PluginCommand {
  XCTestCommand(
    Directory packagesDir,
    FileSystem fileSystem, {
    ProcessRunner processRunner = const ProcessRunner(),
  }) : super(packagesDir, fileSystem, processRunner: processRunner) {
    argParser.addOption(
      _kiOSDestination,
      help:
          'Specify the destination when running the test, used for -destination flag for xcodebuild command.\n'
          'this is passed to the `-destination` argument in xcodebuild command.\n'
          'See https://developer.apple.com/library/archive/technotes/tn2339/_index.html#//apple_ref/doc/uid/DTS40014588-CH1-UNIT for details on how to specify the destination.',
    );
    argParser.addMultiOption(_kSkip,
        help: 'Plugins to skip while running this command. \n');
  }

  @override
  final String name = 'xctest';

  @override
  final String description = 'Runs the xctests in the iOS example apps.\n\n'
      'This command requires "flutter" and "xcrun" to be in your path.';

  @override
  Future<Null> run() async {
    String destination = argResults[_kiOSDestination];
    if (destination == null) {
      String simulatorId = await _findAvailableIphoneSimulator();
      if (simulatorId == null) {
        print(_kFoundNoSimulatorsMessage);
        throw ToolExit(1);
      }
      destination = 'id=$simulatorId';
    }

    checkSharding();

    final List<String> skipped = argResults[_kSkip];

    List<String> failingPackages = <String>[];
    await for (Directory plugin in getPlugins()) {
      // Start running for package.
      final String packageName =
          p.relative(plugin.path, from: packagesDir.path);
      print('Start running for $packageName ...');
      if (!isIosPlugin(plugin, fileSystem)) {
        print('iOS is not supported by this plugin.');
        print('\n\n');
        continue;
      }
      if (skipped.contains(packageName)) {
        print('$packageName was skipped with the --skip flag.');
        print('\n\n');
        continue;
      }
      for (Directory example in getExamplesForPlugin(plugin)) {
        // Running tests and static analyzer.
        print('Running tests and analyzer for $packageName ...');
        int exitCode = await _runTests(true, destination, example);
        // 66 = there is no test target (this fails fast). Try again with just the analyzer.
        if (exitCode == 66) {
          print('Tests not found for $packageName, running analyzer only...');
          exitCode = await _runTests(false, destination, example);
        }
        if (exitCode == 0) {
          print('Successfully ran xctest for $packageName');
        } else {
          failingPackages.add(packageName);
        }
      }
    }

    // Command end, print reports.
    if (failingPackages.isEmpty) {
      print("All XCTests have passed!");
    } else {
      print(
          'The following packages are failing XCTests (see above for details):');
      for (String package in failingPackages) {
        print(' * $package');
      }
      throw ToolExit(1);
    }
  }

  Future<int> _runTests(bool runTests, String destination, Directory example) {
    final List<String> xctestArgs = <String>[
      _kXcodeBuildCommand,
      if (runTests)
        'test',
      'analyze',
      '-workspace',
      'ios/Runner.xcworkspace',
      '-configuration',
      'Debug',
      '-scheme',
      'Runner',
      '-destination',
      destination,
      'CODE_SIGN_IDENTITY=""',
      'CODE_SIGNING_REQUIRED=NO',
      'GCC_TREAT_WARNINGS_AS_ERRORS=YES',
    ];
    final String completeTestCommand =
        '$_kXCRunCommand ${xctestArgs.join(' ')}';
    print(completeTestCommand);
    return processRunner
        .runAndStream(_kXCRunCommand, xctestArgs, workingDir: example, exitOnError: false);
  }

  Future<String> _findAvailableIphoneSimulator() async {
    // Find the first available destination if not specified.
    final List<String> findSimulatorsArguments = <String>[
      'simctl',
      'list',
      '--json'
    ];
    final String findSimulatorCompleteCommand =
        '$_kXCRunCommand ${findSimulatorsArguments.join(' ')}';
    print('Looking for available simulators...');
    print(findSimulatorCompleteCommand);
    final io.ProcessResult findSimulatorsResult =
        await processRunner.run(_kXCRunCommand, findSimulatorsArguments);
    if (findSimulatorsResult.exitCode != 0) {
      print('Error occurred while running "$findSimulatorCompleteCommand":\n'
          '${findSimulatorsResult.stderr}');
      throw ToolExit(1);
    }
    final Map<String, dynamic> simulatorListJson =
        jsonDecode(findSimulatorsResult.stdout);
    final List<dynamic> runtimes = simulatorListJson['runtimes'];
    final Map<String, dynamic> devices = simulatorListJson['devices'];
    if (runtimes.isEmpty || devices.isEmpty) {
      return null;
    }
    String id;
    // Looking for runtimes, trying to find one with highest OS version.
    for (Map<String, dynamic> runtimeMap in runtimes.reversed) {
      if (!runtimeMap['name'].contains('iOS')) {
        continue;
      }
      final String runtimeID = runtimeMap['identifier'];
      final List<dynamic> devicesForRuntime = devices[runtimeID];
      if (devicesForRuntime.isEmpty) {
        continue;
      }
      // Looking for runtimes, trying to find latest version of device.
      for (Map<String, dynamic> device in devicesForRuntime.reversed) {
        if (device['availabilityError'] != null ||
            (device['isAvailable'] as bool == false)) {
          continue;
        }
        id = device['udid'];
        print('device selected: $device');
        return id;
      }
    }
    return null;
  }
}
