// 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/memory.dart';
import 'package:meta/meta.dart';
import 'package:process/process.dart';

import '../artifacts.dart';
import '../base/common.dart';
import '../base/file_system.dart';
import '../base/io.dart';
import '../base/logger.dart';
import '../base/platform.dart';
import '../base/process.dart';
import '../base/version.dart';
import '../build_info.dart';
import '../cache.dart';
import '../convert.dart';
import '../globals.dart' as globals;
import '../ios/devices.dart';
import '../ios/ios_deploy.dart';
import '../ios/iproxy.dart';
import '../ios/mac.dart';
import '../ios/xcodeproj.dart';
import '../reporting/reporting.dart';

Version get xcodeRequiredVersion => Version(12, 0, 1, text: '12.0.1');

/// Diverging this number from the minimum required version will provide a doctor
/// warning, not error, that users should upgrade Xcode.
Version get xcodeRecommendedVersion => xcodeRequiredVersion;

/// SDK name passed to `xcrun --sdk`. Corresponds to undocumented Xcode
/// SUPPORTED_PLATFORMS values.
///
/// Usage: xcrun [options] <tool name> ... arguments ...
/// ...
/// --sdk <sdk name>            find the tool for the given SDK name.
String getSDKNameForIOSEnvironmentType(EnvironmentType environmentType) {
  return (environmentType == EnvironmentType.simulator)
      ? 'iphonesimulator'
      : 'iphoneos';
}

/// A utility class for interacting with Xcode command line tools.
class Xcode {
  Xcode({
    @required Platform platform,
    @required ProcessManager processManager,
    @required Logger logger,
    @required FileSystem fileSystem,
    @required XcodeProjectInterpreter xcodeProjectInterpreter,
  })  : _platform = platform,
        _fileSystem = fileSystem,
        _xcodeProjectInterpreter = xcodeProjectInterpreter,
        _processUtils =
            ProcessUtils(logger: logger, processManager: processManager);

  /// Create an [Xcode] for testing.
  ///
  /// Defaults to a memory file system, fake platform,
  /// buffer logger, and test [XcodeProjectInterpreter].
  @visibleForTesting
  factory Xcode.test({
    @required ProcessManager processManager,
    XcodeProjectInterpreter xcodeProjectInterpreter,
    Platform platform,
    FileSystem fileSystem,
  }) {
    platform ??= FakePlatform(
      operatingSystem: 'macos',
      environment: <String, String>{},
    );
    return Xcode(
      platform: platform,
      processManager: processManager,
      fileSystem: fileSystem ?? MemoryFileSystem.test(),
      logger: BufferLogger.test(),
      xcodeProjectInterpreter: xcodeProjectInterpreter ?? XcodeProjectInterpreter.test(processManager: processManager),
    );
  }

  final Platform _platform;
  final ProcessUtils _processUtils;
  final FileSystem _fileSystem;
  final XcodeProjectInterpreter _xcodeProjectInterpreter;

  bool get isInstalledAndMeetsVersionCheck => _platform.isMacOS && isInstalled && isRequiredVersionSatisfactory;

  String _xcodeSelectPath;
  String get xcodeSelectPath {
    if (_xcodeSelectPath == null) {
      try {
        _xcodeSelectPath = _processUtils.runSync(
          <String>['/usr/bin/xcode-select', '--print-path'],
        ).stdout.trim();
      } on ProcessException {
        // Ignored, return null below.
      } on ArgumentError {
        // Ignored, return null below.
      }
    }
    return _xcodeSelectPath;
  }

  bool get isInstalled => _xcodeProjectInterpreter.isInstalled;

  Version get currentVersion => Version(
        _xcodeProjectInterpreter.majorVersion,
        _xcodeProjectInterpreter.minorVersion,
        _xcodeProjectInterpreter.patchVersion,
        text:
            '${_xcodeProjectInterpreter.majorVersion}.${_xcodeProjectInterpreter.minorVersion}.${_xcodeProjectInterpreter.patchVersion}',
      );

  String get versionText => _xcodeProjectInterpreter.versionText;

  bool _eulaSigned;
  /// Has the EULA been signed?
  bool get eulaSigned {
    if (_eulaSigned == null) {
      try {
        final RunResult result = _processUtils.runSync(
          <String>[...xcrunCommand(), 'clang'],
        );
        if (result.stdout != null && result.stdout.contains('license')) {
          _eulaSigned = false;
        } else if (result.stderr != null && result.stderr.contains('license')) {
          _eulaSigned = false;
        } else {
          _eulaSigned = true;
        }
      } on ProcessException {
        _eulaSigned = false;
      }
    }
    return _eulaSigned;
  }

  bool _isSimctlInstalled;

  /// Verifies that simctl is installed by trying to run it.
  bool get isSimctlInstalled {
    if (_isSimctlInstalled == null) {
      try {
        // This command will error if additional components need to be installed in
        // xcode 9.2 and above.
        final RunResult result = _processUtils.runSync(
          <String>[...xcrunCommand(), 'simctl', 'list'],
        );
        _isSimctlInstalled = result.exitCode == 0;
      } on ProcessException {
        _isSimctlInstalled = false;
      }
    }
    return _isSimctlInstalled;
  }

  bool get isRequiredVersionSatisfactory {
    if (!_xcodeProjectInterpreter.isInstalled) {
      return false;
    }
    return currentVersion >= xcodeRequiredVersion;
  }

  bool get isRecommendedVersionSatisfactory {
    if (!_xcodeProjectInterpreter.isInstalled) {
      return false;
    }
    return currentVersion >= xcodeRecommendedVersion;
  }

  /// See [XcodeProjectInterpreter.xcrunCommand].
  List<String> xcrunCommand() => _xcodeProjectInterpreter.xcrunCommand();

  Future<RunResult> cc(List<String> args) {
    return _processUtils.run(
      <String>[...xcrunCommand(), 'cc', ...args],
      throwOnError: true,
    );
  }

  Future<RunResult> clang(List<String> args) {
    return _processUtils.run(
      <String>[...xcrunCommand(), 'clang', ...args],
      throwOnError: true,
    );
  }

  Future<String> sdkLocation(EnvironmentType environmentType) async {
    assert(environmentType != null);
    final RunResult runResult = await _processUtils.run(
      <String>[...xcrunCommand(), '--sdk', getSDKNameForIOSEnvironmentType(environmentType), '--show-sdk-path'],
    );
    if (runResult.exitCode != 0) {
      throwToolExit('Could not find SDK location: ${runResult.stderr}');
    }
    return runResult.stdout.trim();
  }

  String getSimulatorPath() {
    if (xcodeSelectPath == null) {
      return null;
    }
    final List<String> searchPaths = <String>[
      _fileSystem.path.join(xcodeSelectPath, 'Applications', 'Simulator.app'),
    ];
    return searchPaths.where((String p) => p != null).firstWhere(
      (String p) => _fileSystem.directory(p).existsSync(),
      orElse: () => null,
    );
  }
}

EnvironmentType environmentTypeFromSdkroot(Directory sdkroot) {
  assert(sdkroot != null);
  // iPhoneSimulator.sdk or iPhoneOS.sdk
  final String sdkName = sdkroot.basename.toLowerCase();
  if (sdkName.contains('iphone')) {
    return sdkName.contains('simulator') ? EnvironmentType.simulator : EnvironmentType.physical;
  }
  assert(false);
  return null;
}

enum XCDeviceEvent {
  attach,
  detach,
}

/// A utility class for interacting with Xcode xcdevice command line tools.
class XCDevice {
  XCDevice({
    @required Artifacts artifacts,
    @required Cache cache,
    @required ProcessManager processManager,
    @required Logger logger,
    @required Xcode xcode,
    @required Platform platform,
    @required IProxy iproxy,
  }) : _processUtils = ProcessUtils(logger: logger, processManager: processManager),
      _logger = logger,
      _iMobileDevice = IMobileDevice(
        artifacts: artifacts,
        cache: cache,
        logger: logger,
        processManager: processManager,
      ),
      _iosDeploy = IOSDeploy(
        artifacts: artifacts,
        cache: cache,
        logger: logger,
        platform: platform,
        processManager: processManager,
      ),
      _iProxy = iproxy,
      _xcode = xcode {

    _setupDeviceIdentifierByEventStream();
  }

  void dispose() {
    _deviceObservationProcess?.kill();
  }

  final ProcessUtils _processUtils;
  final Logger _logger;
  final IMobileDevice _iMobileDevice;
  final IOSDeploy _iosDeploy;
  final Xcode _xcode;
  final IProxy _iProxy;

  List<dynamic> _cachedListResults;
  Process _deviceObservationProcess;
  StreamController<Map<XCDeviceEvent, String>> _deviceIdentifierByEvent;

  void _setupDeviceIdentifierByEventStream() {
    // _deviceIdentifierByEvent Should always be available for listeners
    // in case polling needs to be stopped and restarted.
    _deviceIdentifierByEvent = StreamController<Map<XCDeviceEvent, String>>.broadcast(
      onListen: _startObservingTetheredIOSDevices,
      onCancel: _stopObservingTetheredIOSDevices,
    );
  }

  bool get isInstalled => _xcode.isInstalledAndMeetsVersionCheck;

  Future<List<dynamic>> _getAllDevices({
    bool useCache = false,
    @required Duration timeout
  }) async {
    if (!isInstalled) {
      _logger.printTrace("Xcode not found. Run 'flutter doctor' for more information.");
      return null;
    }
    if (useCache && _cachedListResults != null) {
      return _cachedListResults;
    }
    try {
      // USB-tethered devices should be found quickly. 1 second timeout is faster than the default.
      final RunResult result = await _processUtils.run(
        <String>[
          ..._xcode.xcrunCommand(),
          'xcdevice',
          'list',
          '--timeout',
          timeout.inSeconds.toString(),
        ],
        throwOnError: true,
      );
      if (result.exitCode == 0) {
        final List<dynamic> listResults = json.decode(result.stdout) as List<dynamic>;
        _cachedListResults = listResults;
        return listResults;
      }
      _logger.printTrace('xcdevice returned an error:\n${result.stderr}');
    } on ProcessException catch (exception) {
      _logger.printTrace('Process exception running xcdevice list:\n$exception');
    } on ArgumentError catch (exception) {
      _logger.printTrace('Argument exception running xcdevice list:\n$exception');
    }

    return null;
  }

  /// Observe identifiers (UDIDs) of devices as they attach and detach.
  ///
  /// Each attach and detach event is a tuple of one event type
  /// and identifier.
  Stream<Map<XCDeviceEvent, String>> observedDeviceEvents() {
    if (!isInstalled) {
      _logger.printTrace("Xcode not found. Run 'flutter doctor' for more information.");
      return null;
    }
    return _deviceIdentifierByEvent.stream;
  }

  // Attach: d83d5bc53967baa0ee18626ba87b6254b2ab5418
  // Attach: 00008027-00192736010F802E
  // Detach: d83d5bc53967baa0ee18626ba87b6254b2ab5418
  final RegExp _observationIdentifierPattern = RegExp(r'^(\w*): ([\w-]*)$');

  Future<void> _startObservingTetheredIOSDevices() async {
    try {
      if (_deviceObservationProcess != null) {
        throw Exception('xcdevice observe restart failed');
      }

      // Run in interactive mode (via script) to convince
      // xcdevice it has a terminal attached in order to redirect stdout.
      _deviceObservationProcess = await _processUtils.start(
        <String>[
          'script',
          '-t',
          '0',
          '/dev/null',
          ..._xcode.xcrunCommand(),
          'xcdevice',
          'observe',
          '--both',
        ],
      );

      final StreamSubscription<String> stdoutSubscription = _deviceObservationProcess.stdout
        .transform<String>(utf8.decoder)
        .transform<String>(const LineSplitter())
        .listen((String line) {

        // xcdevice observe example output of UDIDs:
        //
        // Listening for all devices, on both interfaces.
        // Attach: d83d5bc53967baa0ee18626ba87b6254b2ab5418
        // Attach: 00008027-00192736010F802E
        // Detach: d83d5bc53967baa0ee18626ba87b6254b2ab5418
        // Attach: d83d5bc53967baa0ee18626ba87b6254b2ab5418
        final RegExpMatch match = _observationIdentifierPattern.firstMatch(line);
        if (match != null && match.groupCount == 2) {
          final String verb = match.group(1).toLowerCase();
          final String identifier = match.group(2);
          if (verb.startsWith('attach')) {
            _deviceIdentifierByEvent.add(<XCDeviceEvent, String>{
              XCDeviceEvent.attach: identifier
            });
          } else if (verb.startsWith('detach')) {
            _deviceIdentifierByEvent.add(<XCDeviceEvent, String>{
              XCDeviceEvent.detach: identifier
            });
          }
        }
      });
      final StreamSubscription<String> stderrSubscription = _deviceObservationProcess.stderr
        .transform<String>(utf8.decoder)
        .transform<String>(const LineSplitter())
        .listen((String line) {
        _logger.printTrace('xcdevice observe error: $line');
      });
      unawaited(_deviceObservationProcess.exitCode.then((int status) {
        _logger.printTrace('xcdevice exited with code $exitCode');
        unawaited(stdoutSubscription.cancel());
        unawaited(stderrSubscription.cancel());
      }).whenComplete(() async {
        if (_deviceIdentifierByEvent.hasListener) {
          // Tell listeners the process died.
          await _deviceIdentifierByEvent.close();
        }
        _deviceObservationProcess = null;

        // Reopen it so new listeners can resume polling.
        _setupDeviceIdentifierByEventStream();
      }));
    } on ProcessException catch (exception, stackTrace) {
      _deviceIdentifierByEvent.addError(exception, stackTrace);
    } on ArgumentError catch (exception, stackTrace) {
      _deviceIdentifierByEvent.addError(exception, stackTrace);
    }
  }

  void _stopObservingTetheredIOSDevices() {
    _deviceObservationProcess?.kill();
  }

  /// [timeout] defaults to 2 seconds.
  Future<List<IOSDevice>> getAvailableIOSDevices({ Duration timeout }) async {
    final List<dynamic> allAvailableDevices = await _getAllDevices(timeout: timeout ?? const Duration(seconds: 2));

    if (allAvailableDevices == null) {
      return const <IOSDevice>[];
    }

    // [
    //  {
    //    "simulator" : true,
    //    "operatingSystemVersion" : "13.3 (17K446)",
    //    "available" : true,
    //    "platform" : "com.apple.platform.appletvsimulator",
    //    "modelCode" : "AppleTV5,3",
    //    "identifier" : "CBB5E1ED-2172-446E-B4E7-F2B5823DBBA6",
    //    "architecture" : "x86_64",
    //    "modelName" : "Apple TV",
    //    "name" : "Apple TV"
    //  },
    //  {
    //    "simulator" : false,
    //    "operatingSystemVersion" : "13.3 (17C54)",
    //    "interface" : "usb",
    //    "available" : true,
    //    "platform" : "com.apple.platform.iphoneos",
    //    "modelCode" : "iPhone8,1",
    //    "identifier" : "d83d5bc53967baa0ee18626ba87b6254b2ab5418",
    //    "architecture" : "arm64",
    //    "modelName" : "iPhone 6s",
    //    "name" : "iPhone"
    //  },
    //  {
    //    "simulator" : true,
    //    "operatingSystemVersion" : "6.1.1 (17S445)",
    //    "available" : true,
    //    "platform" : "com.apple.platform.watchsimulator",
    //    "modelCode" : "Watch5,4",
    //    "identifier" : "2D74FB11-88A0-44D0-B81E-C0C142B1C94A",
    //    "architecture" : "i386",
    //    "modelName" : "Apple Watch Series 5 - 44mm",
    //    "name" : "Apple Watch Series 5 - 44mm"
    //  },
    // ...

    final List<IOSDevice> devices = <IOSDevice>[];
    for (final dynamic device in allAvailableDevices) {
      if (device is! Map) {
        continue;
      }
      final Map<String, dynamic> deviceProperties = device as Map<String, dynamic>;

      // Only include iPhone, iPad, iPod, or other iOS devices.
      if (!_isIPhoneOSDevice(deviceProperties)) {
        continue;
      }

      final Map<String, dynamic> errorProperties = _errorProperties(deviceProperties);
      if (errorProperties != null) {
        final String errorMessage = _parseErrorMessage(errorProperties);
        if (errorMessage.contains('not paired')) {
          UsageEvent('device', 'ios-trust-failure', flutterUsage: globals.flutterUsage).send();
        }
        _logger.printTrace(errorMessage);

        final int code = _errorCode(errorProperties);

        // Temporary error -10: iPhone is busy: Preparing debugger support for iPhone.
        // Sometimes the app launch will fail on these devices until Xcode is done setting up the device.
        // Other times this is a false positive and the app will successfully launch despite the error.
        if (code != -10) {
          continue;
        }
      }

      final IOSDeviceInterface interface = _interfaceType(deviceProperties);

      // Only support USB devices, skip "network" interface (Xcode > Window > Devices and Simulators > Connect via network).
      // TODO(jmagman): Remove this check once wirelessly detected devices can be observed and attached, https://github.com/flutter/flutter/issues/15072.
      if (interface != IOSDeviceInterface.usb) {
        continue;
      }

      devices.add(IOSDevice(
        device['identifier'] as String,
        name: device['name'] as String,
        cpuArchitecture: _cpuArchitecture(deviceProperties),
        interfaceType: interface,
        sdkVersion: _sdkVersion(deviceProperties),
        iProxy: _iProxy,
        fileSystem: globals.fs,
        logger: _logger,
        iosDeploy: _iosDeploy,
        iMobileDevice: _iMobileDevice,
        platform: globals.platform,
      ));
    }
    return devices;
  }

  /// Despite the name, com.apple.platform.iphoneos includes iPhone, iPads, and all iOS devices.
  /// Excludes simulators.
  static bool _isIPhoneOSDevice(Map<String, dynamic> deviceProperties) {
    if (deviceProperties.containsKey('platform')) {
      final String platform = deviceProperties['platform'] as String;
      return platform == 'com.apple.platform.iphoneos';
    }
    return false;
  }

  static Map<String, dynamic> _errorProperties(Map<String, dynamic> deviceProperties) {
    if (deviceProperties.containsKey('error')) {
      return deviceProperties['error'] as Map<String, dynamic>;
    }
    return null;
  }

  static int _errorCode(Map<String, dynamic> errorProperties) {
    if (errorProperties.containsKey('code') && errorProperties['code'] is int) {
      return errorProperties['code'] as int;
    }
    return null;
  }

  static IOSDeviceInterface _interfaceType(Map<String, dynamic> deviceProperties) {
    // Interface can be "usb", "network", or "none" for simulators
    // and unknown future interfaces.
    if (deviceProperties.containsKey('interface')) {
      if ((deviceProperties['interface'] as String).toLowerCase() == 'network') {
        return IOSDeviceInterface.network;
      } else {
        return IOSDeviceInterface.usb;
      }
    }

    return IOSDeviceInterface.none;
  }

  static String _sdkVersion(Map<String, dynamic> deviceProperties) {
    if (deviceProperties.containsKey('operatingSystemVersion')) {
      // Parse out the OS version, ignore the build number in parentheses.
      // "13.3 (17C54)"
      final RegExp operatingSystemRegex = RegExp(r'(.*) \(.*\)$');
      final String operatingSystemVersion = deviceProperties['operatingSystemVersion'] as String;
      return operatingSystemRegex.firstMatch(operatingSystemVersion.trim())?.group(1);
    }
    return null;
  }

  DarwinArch _cpuArchitecture(Map<String, dynamic> deviceProperties) {
    DarwinArch cpuArchitecture;
    if (deviceProperties.containsKey('architecture')) {
      final String architecture = deviceProperties['architecture'] as String;
      try {
        cpuArchitecture = getIOSArchForName(architecture);
      } on Exception {
        // Fallback to default iOS architecture. Future-proof against a
        // theoretical version of Xcode that changes this string to something
        // slightly different like "ARM64", or armv7 variations like
        // armv7s and armv7f.
        if (architecture.startsWith('armv7')) {
          cpuArchitecture = DarwinArch.armv7;
        } else {
          cpuArchitecture = DarwinArch.arm64;
        }
        _logger.printError(
          'Unknown architecture $architecture, defaulting to '
          '${getNameForDarwinArch(cpuArchitecture)}',
        );
      }
    }
    return cpuArchitecture;
  }

  /// Error message parsed from xcdevice. null if no error.
  static String _parseErrorMessage(Map<String, dynamic> errorProperties) {
    //  {
    //    "simulator" : false,
    //    "operatingSystemVersion" : "13.3 (17C54)",
    //    "interface" : "usb",
    //    "available" : false,
    //    "platform" : "com.apple.platform.iphoneos",
    //    "modelCode" : "iPhone8,1",
    //    "identifier" : "98206e7a4afd4aedaff06e687594e089dede3c44",
    //    "architecture" : "arm64",
    //    "modelName" : "iPhone 6s",
    //    "name" : "iPhone",
    //    "error" : {
    //      "code" : -9,
    //      "failureReason" : "",
    //      "underlyingErrors" : [
    //        {
    //          "code" : 5,
    //          "failureReason" : "allowsSecureServices: 1. isConnected: 0. Platform: <DVTPlatform:0x7f804ce32880:'com.apple.platform.iphoneos':<DVTFilePath:0x7f804ce32800:'\/Users\/magder\/Applications\/Xcode_11-3-1.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform'>>. DTDKDeviceIdentifierIsIDID: 0",
    //          "description" : "📱<DVTiOSDevice (0x7f801f190450), iPhone, iPhone, 13.3 (17C54), d83d5bc53967baa0ee18626ba87b6254b2ab5418> -- Failed _shouldMakeReadyForDevelopment check even though device is not locked by passcode.",
    //          "recoverySuggestion" : "",
    //          "domain" : "com.apple.platform.iphoneos"
    //        }
    //      ],
    //      "description" : "iPhone is not paired with your computer.",
    //      "recoverySuggestion" : "To use iPhone with Xcode, unlock it and choose to trust this computer when prompted.",
    //      "domain" : "com.apple.platform.iphoneos"
    //    }
    //  },
    //  {
    //    "simulator" : false,
    //    "operatingSystemVersion" : "13.3 (17C54)",
    //    "interface" : "usb",
    //    "available" : false,
    //    "platform" : "com.apple.platform.iphoneos",
    //    "modelCode" : "iPhone8,1",
    //    "identifier" : "d83d5bc53967baa0ee18626ba87b6254b2ab5418",
    //    "architecture" : "arm64",
    //    "modelName" : "iPhone 6s",
    //    "name" : "iPhone",
    //    "error" : {
    //      "code" : -9,
    //      "failureReason" : "",
    //      "description" : "iPhone is not paired with your computer.",
    //      "domain" : "com.apple.platform.iphoneos"
    //    }
    //  }
    // ...

    if (errorProperties == null) {
      return null;
    }

    final StringBuffer errorMessage = StringBuffer('Error: ');

    if (errorProperties.containsKey('description')) {
      final String description = errorProperties['description'] as String;
      errorMessage.write(description);
      if (!description.endsWith('.')) {
        errorMessage.write('.');
      }
    } else {
      errorMessage.write('Xcode pairing error.');
    }

    if (errorProperties.containsKey('recoverySuggestion')) {
      final String recoverySuggestion = errorProperties['recoverySuggestion'] as String;
      errorMessage.write(' $recoverySuggestion');
    }

    final int code = _errorCode(errorProperties);
    if (code != null) {
      errorMessage.write(' (code $code)');
    }

    return errorMessage.toString();
  }

  /// List of all devices reporting errors.
  Future<List<String>> getDiagnostics() async {
    final List<dynamic> allAvailableDevices = await _getAllDevices(
      useCache: true,
      timeout: const Duration(seconds: 2)
    );

    if (allAvailableDevices == null) {
      return const <String>[];
    }

    final List<String> diagnostics = <String>[];
    for (final dynamic device in allAvailableDevices) {
      if (device is! Map) {
        continue;
      }
      final Map<String, dynamic> deviceProperties = device as Map<String, dynamic>;
      final Map<String, dynamic> errorProperties = _errorProperties(deviceProperties);
      final String errorMessage = _parseErrorMessage(errorProperties);
      if (errorMessage != null) {
        diagnostics.add(errorMessage);
      }
    }
    return diagnostics;
  }
}
