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

import 'package:file/file.dart';

import 'output_utils.dart';
import 'process_runner.dart';

const String _xcodeBuildCommand = 'xcodebuild';
const String _xcRunCommand = 'xcrun';

/// A utility class for interacting with the installed version of Xcode.
class Xcode {
  /// Creates an instance that runs commands with the given [processRunner].
  ///
  /// If [log] is true, commands run by this instance will long various status
  /// messages.
  Xcode({
    this.processRunner = const ProcessRunner(),
    this.log = false,
  });

  /// The [ProcessRunner] used to run commands. Overridable for testing.
  final ProcessRunner processRunner;

  /// Whether or not to log when running commands.
  final bool log;

  /// Runs an `xcodebuild` in [directory] with the given parameters.
  Future<int> runXcodeBuild(
    Directory directory, {
    List<String> actions = const <String>['build'],
    required String workspace,
    required String scheme,
    String? configuration,
    List<String> extraFlags = const <String>[],
  }) {
    final List<String> args = <String>[
      _xcodeBuildCommand,
      ...actions,
      ...<String>['-workspace', workspace],
      ...<String>['-scheme', scheme],
      if (configuration != null) ...<String>['-configuration', configuration],
      ...extraFlags,
    ];
    final String completeTestCommand = '$_xcRunCommand ${args.join(' ')}';
    if (log) {
      print(completeTestCommand);
    }
    return processRunner.runAndStream(_xcRunCommand, args,
        workingDir: directory);
  }

  /// Returns true if [project], which should be an .xcodeproj directory,
  /// contains a target called [target], false if it does not, and null if the
  /// check fails (e.g., if [project] is not an Xcode project).
  Future<bool?> projectHasTarget(Directory project, String target) async {
    final io.ProcessResult result =
        await processRunner.run(_xcRunCommand, <String>[
      _xcodeBuildCommand,
      '-list',
      '-json',
      '-project',
      project.path,
    ]);
    if (result.exitCode != 0) {
      return null;
    }
    Map<String, dynamic>? projectInfo;
    try {
      projectInfo = (jsonDecode(result.stdout as String)
          as Map<String, dynamic>)['project'] as Map<String, dynamic>?;
    } on FormatException {
      return null;
    }
    if (projectInfo == null) {
      return null;
    }
    final List<String>? targets =
        (projectInfo['targets'] as List<dynamic>?)?.cast<String>();
    return targets?.contains(target) ?? false;
  }

  /// Returns the newest available simulator (highest OS version, with ties
  /// broken in favor of newest device), if any.
  Future<String?> findBestAvailableIphoneSimulator() async {
    final List<String> findSimulatorsArguments = <String>[
      'simctl',
      'list',
      'devices',
      'runtimes',
      'available',
      '--json',
    ];
    final String findSimulatorCompleteCommand =
        '$_xcRunCommand ${findSimulatorsArguments.join(' ')}';
    if (log) {
      print('Looking for available simulators...');
      print(findSimulatorCompleteCommand);
    }
    final io.ProcessResult findSimulatorsResult =
        await processRunner.run(_xcRunCommand, findSimulatorsArguments);
    if (findSimulatorsResult.exitCode != 0) {
      if (log) {
        printError(
            'Error occurred while running "$findSimulatorCompleteCommand":\n'
            '${findSimulatorsResult.stderr}');
      }
      return null;
    }
    final Map<String, dynamic> simulatorListJson =
        jsonDecode(findSimulatorsResult.stdout as String)
            as Map<String, dynamic>;
    final List<Map<String, dynamic>> runtimes =
        (simulatorListJson['runtimes'] as List<dynamic>)
            .cast<Map<String, dynamic>>();
    final Map<String, Object> devices =
        (simulatorListJson['devices'] as Map<String, dynamic>)
            .cast<String, Object>();
    if (runtimes.isEmpty || devices.isEmpty) {
      return null;
    }
    String? id;
    // Looking for runtimes, trying to find one with highest OS version.
    for (final Map<String, dynamic> rawRuntimeMap in runtimes.reversed) {
      final Map<String, Object> runtimeMap =
          rawRuntimeMap.cast<String, Object>();
      if ((runtimeMap['name'] as String?)?.contains('iOS') != true) {
        continue;
      }
      final String? runtimeID = runtimeMap['identifier'] as String?;
      if (runtimeID == null) {
        continue;
      }
      final List<Map<String, dynamic>>? devicesForRuntime =
          (devices[runtimeID] as List<dynamic>?)?.cast<Map<String, dynamic>>();
      if (devicesForRuntime == null || devicesForRuntime.isEmpty) {
        continue;
      }
      // Looking for runtimes, trying to find latest version of device.
      for (final Map<String, dynamic> rawDevice in devicesForRuntime.reversed) {
        final Map<String, Object> device = rawDevice.cast<String, Object>();
        id = device['udid'] as String?;
        if (id == null) {
          continue;
        }
        if (log) {
          print('device selected: $device');
        }
        return id;
      }
    }
    return null;
  }
}
