// 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 'core.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;
  }
}
