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

import 'dart:async';

import 'package:meta/meta.dart';
import 'package:process/process.dart';

import '../artifacts.dart';
import '../base/file_system.dart';
import '../base/io.dart';
import '../base/logger.dart';
import '../base/platform.dart';
import '../base/process.dart';
import '../cache.dart';
import '../convert.dart';
import 'code_signing.dart';
import 'iproxy.dart';

// Error message patterns from ios-deploy output
const String noProvisioningProfileErrorOne = 'Error 0xe8008015';
const String noProvisioningProfileErrorTwo = 'Error 0xe8000067';
const String deviceLockedError = 'e80000e2';
const String unknownAppLaunchError = 'Error 0xe8000022';

class IOSDeploy {
  IOSDeploy({
    required Artifacts artifacts,
    required Cache cache,
    required Logger logger,
    required Platform platform,
    required ProcessManager processManager,
  }) : _platform = platform,
       _cache = cache,
       _processUtils = ProcessUtils(processManager: processManager, logger: logger),
       _logger = logger,
       _binaryPath = artifacts.getHostArtifact(HostArtifact.iosDeploy).path;

  final Cache _cache;
  final String _binaryPath;
  final Logger _logger;
  final Platform _platform;
  final ProcessUtils _processUtils;

  Map<String, String> get iosDeployEnv {
    // Push /usr/bin to the front of PATH to pick up default system python, package 'six'.
    //
    // ios-deploy transitively depends on LLDB.framework, which invokes a
    // Python script that uses package 'six'. LLDB.framework relies on the
    // python at the front of the path, which may not include package 'six'.
    // Ensure that we pick up the system install of python, which includes it.
    final Map<String, String> environment = Map<String, String>.of(_platform.environment);
    environment['PATH'] = '/usr/bin:${environment['PATH']}';
    environment.addEntries(<MapEntry<String, String>>[_cache.dyLdLibEntry]);
    return environment;
  }

  /// Uninstalls the specified app bundle.
  ///
  /// Uses ios-deploy and returns the exit code.
  Future<int> uninstallApp({
    required String deviceId,
    required String bundleId,
  }) async {
    final List<String> launchCommand = <String>[
      _binaryPath,
      '--id',
      deviceId,
      '--uninstall_only',
      '--bundle_id',
      bundleId,
    ];

    return _processUtils.stream(
      launchCommand,
      mapFunction: _monitorFailure,
      trace: true,
      environment: iosDeployEnv,
    );
  }

  /// Installs the specified app bundle.
  ///
  /// Uses ios-deploy and returns the exit code.
  Future<int> installApp({
    required String deviceId,
    required String bundlePath,
    required List<String>launchArguments,
    required IOSDeviceConnectionInterface interfaceType,
    Directory? appDeltaDirectory,
  }) async {
    appDeltaDirectory?.createSync(recursive: true);
    final List<String> launchCommand = <String>[
      _binaryPath,
      '--id',
      deviceId,
      '--bundle',
      bundlePath,
      if (appDeltaDirectory != null) ...<String>[
        '--app_deltas',
        appDeltaDirectory.path,
      ],
      if (interfaceType != IOSDeviceConnectionInterface.network)
        '--no-wifi',
      if (launchArguments.isNotEmpty) ...<String>[
        '--args',
        launchArguments.join(' '),
      ],
    ];

    return _processUtils.stream(
      launchCommand,
      mapFunction: _monitorFailure,
      trace: true,
      environment: iosDeployEnv,
    );
  }

  /// Returns [IOSDeployDebugger] wrapping attached debugger logic.
  ///
  /// This method does not install the app. Call [IOSDeployDebugger.launchAndAttach()]
  /// to install and attach the debugger to the specified app bundle.
  IOSDeployDebugger prepareDebuggerForLaunch({
    required String deviceId,
    required String bundlePath,
    required List<String> launchArguments,
    required IOSDeviceConnectionInterface interfaceType,
    Directory? appDeltaDirectory,
    required bool uninstallFirst,
  }) {
    appDeltaDirectory?.createSync(recursive: true);
    // Interactive debug session to support sending the lldb detach command.
    final List<String> launchCommand = <String>[
      'script',
      '-t',
      '0',
      '/dev/null',
      _binaryPath,
      '--id',
      deviceId,
      '--bundle',
      bundlePath,
      if (appDeltaDirectory != null) ...<String>[
        '--app_deltas',
        appDeltaDirectory.path,
      ],
      if (uninstallFirst)
        '--uninstall',
      '--debug',
      if (interfaceType != IOSDeviceConnectionInterface.network)
        '--no-wifi',
      if (launchArguments.isNotEmpty) ...<String>[
        '--args',
        launchArguments.join(' '),
      ],
    ];
    return IOSDeployDebugger(
      launchCommand: launchCommand,
      logger: _logger,
      processUtils: _processUtils,
      iosDeployEnv: iosDeployEnv,
    );
  }

  /// Installs and then runs the specified app bundle.
  ///
  /// Uses ios-deploy and returns the exit code.
  Future<int> launchApp({
    required String deviceId,
    required String bundlePath,
    required List<String> launchArguments,
    required IOSDeviceConnectionInterface interfaceType,
    required bool uninstallFirst,
    Directory? appDeltaDirectory,
  }) async {
    appDeltaDirectory?.createSync(recursive: true);
    final List<String> launchCommand = <String>[
      _binaryPath,
      '--id',
      deviceId,
      '--bundle',
      bundlePath,
      if (appDeltaDirectory != null) ...<String>[
        '--app_deltas',
        appDeltaDirectory.path,
      ],
      if (interfaceType != IOSDeviceConnectionInterface.network)
        '--no-wifi',
      if (uninstallFirst)
        '--uninstall',
      '--justlaunch',
      if (launchArguments.isNotEmpty) ...<String>[
        '--args',
        launchArguments.join(' '),
      ],
    ];

    return _processUtils.stream(
      launchCommand,
      mapFunction: _monitorFailure,
      trace: true,
      environment: iosDeployEnv,
    );
  }

  Future<bool> isAppInstalled({
    required String bundleId,
    required String deviceId,
  }) async {
    final List<String> launchCommand = <String>[
      _binaryPath,
      '--id',
      deviceId,
      '--exists',
      '--timeout', // If the device is not connected, ios-deploy will wait forever.
      '10',
      '--bundle_id',
      bundleId,
    ];
    final RunResult result = await _processUtils.run(
      launchCommand,
      environment: iosDeployEnv,
    );
    // Device successfully connected, but app not installed.
    if (result.exitCode == 255) {
      _logger.printTrace('$bundleId not installed on $deviceId');
      return false;
    }
    if (result.exitCode != 0) {
      _logger.printTrace('App install check failed: ${result.stderr}');
      return false;
    }
    return true;
  }

  String _monitorFailure(String stdout) => _monitorIOSDeployFailure(stdout, _logger);
}

/// lldb attach state flow.
enum _IOSDeployDebuggerState {
  detached,
  launching,
  attached,
}

/// Wrapper to launch app and attach the debugger with ios-deploy.
class IOSDeployDebugger {
  IOSDeployDebugger({
    required Logger logger,
    required ProcessUtils processUtils,
    required List<String> launchCommand,
    required Map<String, String> iosDeployEnv,
  }) : _processUtils = processUtils,
        _logger = logger,
        _launchCommand = launchCommand,
        _iosDeployEnv = iosDeployEnv,
        _debuggerState = _IOSDeployDebuggerState.detached;

  /// Create a [IOSDeployDebugger] for testing.
  ///
  /// Sets the command to "ios-deploy" and environment to an empty map.
  @visibleForTesting
  factory IOSDeployDebugger.test({
    required ProcessManager processManager,
    Logger? logger,
  }) {
    final Logger debugLogger = logger ?? BufferLogger.test();
    return IOSDeployDebugger(
      logger: debugLogger,
      processUtils: ProcessUtils(logger: debugLogger, processManager: processManager),
      launchCommand: <String>['ios-deploy'],
      iosDeployEnv: <String, String>{},
    );
  }

  final Logger _logger;
  final ProcessUtils _processUtils;
  final List<String> _launchCommand;
  final Map<String, String> _iosDeployEnv;

  Process? _iosDeployProcess;

  Stream<String> get logLines => _debuggerOutput.stream;
  final StreamController<String> _debuggerOutput = StreamController<String>.broadcast();

  bool get debuggerAttached => _debuggerState == _IOSDeployDebuggerState.attached;
  _IOSDeployDebuggerState _debuggerState;

  // (lldb)     run
  // https://github.com/ios-control/ios-deploy/blob/1.11.2-beta.1/src/ios-deploy/ios-deploy.m#L51
  static final RegExp _lldbRun = RegExp(r'\(lldb\)\s*run');

  // (lldb)     run
  // https://github.com/ios-control/ios-deploy/blob/1.11.2-beta.1/src/ios-deploy/ios-deploy.m#L51
  static final RegExp _lldbProcessExit = RegExp(r'Process \d* exited with status =');

  // (lldb) Process 6152 stopped
  static final RegExp _lldbProcessStopped = RegExp(r'Process \d* stopped');

  // (lldb) Process 6152 detached
  static final RegExp _lldbProcessDetached = RegExp(r'Process \d* detached');

  // (lldb) Process 6152 resuming
  static final RegExp _lldbProcessResuming = RegExp(r'Process \d+ resuming');

  // Send signal to stop (pause) the app. Used before a backtrace dump.
  static const String _signalStop = 'process signal SIGSTOP';

  static const String _processResume = 'process continue';
  static const String _processInterrupt = 'process interrupt';

  // Print backtrace for all threads while app is stopped.
  static const String _backTraceAll = 'thread backtrace all';

  /// If this is non-null, then the app process is paused and awaiting backtrace logging.
  ///
  /// The future should be completed once the backtraces are logged.
  Completer<void>? _processResumeCompleter;

  /// Launch the app on the device, and attach the debugger.
  ///
  /// Returns whether or not the debugger successfully attached.
  Future<bool> launchAndAttach() async {
    // Return when the debugger attaches, or the ios-deploy process exits.
    final Completer<bool> debuggerCompleter = Completer<bool>();
    try {
      _iosDeployProcess = await _processUtils.start(
        _launchCommand,
        environment: _iosDeployEnv,
      );
      String? lastLineFromDebugger;
      final StreamSubscription<String> stdoutSubscription = _iosDeployProcess!.stdout
          .transform<String>(utf8.decoder)
          .transform<String>(const LineSplitter())
          .listen((String line) {
        _monitorIOSDeployFailure(line, _logger);
        // (lldb)     run
        // success
        // 2020-09-15 13:42:25.185474-0700 Runner[477:181141] flutter: The Dart VM service is listening on http://127.0.0.1:57782/
        if (_lldbRun.hasMatch(line)) {
          _logger.printTrace(line);
          _debuggerState = _IOSDeployDebuggerState.launching;
          return;
        }
        // Next line after "run" must be "success", or the attach failed.
        // Example: "error: process launch failed"
        if (_debuggerState == _IOSDeployDebuggerState.launching) {
          _logger.printTrace(line);
          final bool attachSuccess = line == 'success';
          _debuggerState = attachSuccess ? _IOSDeployDebuggerState.attached : _IOSDeployDebuggerState.detached;
          if (!debuggerCompleter.isCompleted) {
            debuggerCompleter.complete(attachSuccess);
          }
          return;
        }
        if (line == _signalStop) {
          // The app is about to be stopped. Only show in verbose mode.
          _logger.printTrace(line);
          return;
        }
        if (line == _backTraceAll) {
          // The app is stopped and the backtrace for all threads will be printed.
          _logger.printTrace(line);
          // Even though we're not "detached", just stopped, mark as detached so the backtrace
          // is only show in verbose.
          _debuggerState = _IOSDeployDebuggerState.detached;

          // If we paused the app and are waiting to resume it, complete the completer
          final Completer<void>? processResumeCompleter = _processResumeCompleter;
          if (processResumeCompleter != null) {
            _processResumeCompleter = null;
            processResumeCompleter.complete();
          }
          return;
        }

        if (line.contains('PROCESS_STOPPED') || _lldbProcessStopped.hasMatch(line)) {
          // The app has been stopped. Dump the backtrace, and detach.
          _logger.printTrace(line);
          _iosDeployProcess?.stdin.writeln(_backTraceAll);
          if (_processResumeCompleter == null) {
            detach();
          }
          return;
        }

        if (line.contains('PROCESS_EXITED') || _lldbProcessExit.hasMatch(line)) {
          // The app exited or crashed, so exit. Continue passing debugging
          // messages to the log reader until it exits to capture crash dumps.
          _logger.printTrace(line);
          exit();
          return;
        }
        if (_lldbProcessDetached.hasMatch(line)) {
          // The debugger has detached from the app, and there will be no more debugging messages.
          // Kill the ios-deploy process.
          exit();
          return;
        }

        if (_lldbProcessResuming.hasMatch(line)) {
          _logger.printTrace(line);
          // we marked this detached when we received [_backTraceAll]
          _debuggerState = _IOSDeployDebuggerState.attached;
          return;
        }

        if (_debuggerState != _IOSDeployDebuggerState.attached) {
          _logger.printTrace(line);
          return;
        }
        if (lastLineFromDebugger != null && lastLineFromDebugger!.isNotEmpty && line.isEmpty) {
          // The lldb console stream from ios-deploy is separated lines by an extra \r\n.
          // To avoid all lines being double spaced, if the last line from the
          // debugger was not an empty line, skip this empty line.
          // This will still cause "legit" logged newlines to be doubled...
        } else if (!_debuggerOutput.isClosed) {
          _debuggerOutput.add(line);
        }
        lastLineFromDebugger = line;
      });
      final StreamSubscription<String> stderrSubscription = _iosDeployProcess!.stderr
          .transform<String>(utf8.decoder)
          .transform<String>(const LineSplitter())
          .listen((String line) {
        _monitorIOSDeployFailure(line, _logger);
        _logger.printTrace(line);
      });
      unawaited(_iosDeployProcess!.exitCode.then((int status) async {
        _logger.printTrace('ios-deploy exited with code $exitCode');
        _debuggerState = _IOSDeployDebuggerState.detached;
        await stdoutSubscription.cancel();
        await stderrSubscription.cancel();
      }).whenComplete(() async {
        if (_debuggerOutput.hasListener) {
          // Tell listeners the process died.
          await _debuggerOutput.close();
        }
        if (!debuggerCompleter.isCompleted) {
          debuggerCompleter.complete(false);
        }
        _iosDeployProcess = null;
      }));
    } on ProcessException catch (exception, stackTrace) {
      _logger.printTrace('ios-deploy failed: $exception');
      _debuggerState = _IOSDeployDebuggerState.detached;
      if (!_debuggerOutput.isClosed) {
        _debuggerOutput.addError(exception, stackTrace);
      }
    } on ArgumentError catch (exception, stackTrace) {
      _logger.printTrace('ios-deploy failed: $exception');
      _debuggerState = _IOSDeployDebuggerState.detached;
      if (!_debuggerOutput.isClosed) {
        _debuggerOutput.addError(exception, stackTrace);
      }
    }
    // Wait until the debugger attaches, or the attempt fails.
    return debuggerCompleter.future;
  }

  bool exit() {
    final bool success = (_iosDeployProcess == null) || _iosDeployProcess!.kill();
    _iosDeployProcess = null;
    return success;
  }

  /// Pause app, dump backtrace for debugging, and resume.
  Future<void> pauseDumpBacktraceResume() async {
    if (!debuggerAttached) {
      return;
    }
    final Completer<void> completer = Completer<void>();
    _processResumeCompleter = completer;
    try {
      // Stop the app, which will prompt the backtrace to be printed for all threads in the stdoutSubscription handler.
      _iosDeployProcess?.stdin.writeln(_processInterrupt);
    } on SocketException catch (error) {
      _logger.printTrace('Could not stop app from debugger: $error');
    }
    // wait for backtrace to be dumped
    await completer.future;
    _iosDeployProcess?.stdin.writeln(_processResume);
  }

  Future<void> stopAndDumpBacktrace() async {
    if (!debuggerAttached) {
      return;
    }
    try {
      // Stop the app, which will prompt the backtrace to be printed for all threads in the stdoutSubscription handler.
      _iosDeployProcess?.stdin.writeln(_signalStop);
    } on SocketException catch (error) {
      // Best effort, try to detach, but maybe the app already exited or already detached.
      _logger.printTrace('Could not stop app from debugger: $error');
    }
    // Wait for logging to finish on process exit.
    return logLines.drain();
  }

  void detach() {
    if (!debuggerAttached) {
      return;
    }

    try {
      // Detach lldb from the app process.
      _iosDeployProcess?.stdin.writeln('process detach');
    } on SocketException catch (error) {
      // Best effort, try to detach, but maybe the app already exited or already detached.
      _logger.printTrace('Could not detach from debugger: $error');
    }
  }
}

// Maps stdout line stream. Must return original line.
String _monitorIOSDeployFailure(String stdout, Logger logger) {
  // Installation issues.
  if (stdout.contains(noProvisioningProfileErrorOne) || stdout.contains(noProvisioningProfileErrorTwo)) {
    logger.printError(noProvisioningProfileInstruction, emphasis: true);

    // Launch issues.
  } else if (stdout.contains(deviceLockedError)) {
    logger.printError('''
═══════════════════════════════════════════════════════════════════════════════════
Your device is locked. Unlock your device first before running.
═══════════════════════════════════════════════════════════════════════════════════''',
        emphasis: true);
  } else if (stdout.contains(unknownAppLaunchError)) {
    logger.printError('''
═══════════════════════════════════════════════════════════════════════════════════
Error launching app. Try launching from within Xcode via:
    open ios/Runner.xcworkspace

Your Xcode version may be too old for your iOS version.
═══════════════════════════════════════════════════════════════════════════════════''',
        emphasis: true);
  }

  return stdout;
}
