// 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:io';

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

@immutable
class RunningProcessInfo {
  const RunningProcessInfo(this.pid, this.creationDate, this.commandLine)
      : assert(pid != null),
        assert(commandLine != null);

  final String commandLine;
  final String pid;
  final DateTime creationDate;

  @override
  bool operator ==(Object other) {
    return other is RunningProcessInfo &&
        other.pid == pid &&
        other.commandLine == commandLine &&
        other.creationDate == creationDate;
  }

  @override
  int get hashCode {
    // TODO(dnfield): Replace this when Object.hashValues lands.
    int hash = 17;
    if (pid != null) {
      hash = hash * 23 + pid.hashCode;
    }
    if (commandLine != null) {
      hash = hash * 23 + commandLine.hashCode;
    }
    if (creationDate != null) {
      hash = hash * 23 + creationDate.hashCode;
    }
    return hash;
  }

  @override
  String toString() {
    return 'RunningProcesses{pid: $pid, commandLine: $commandLine, creationDate: $creationDate}';
  }
}

Future<bool> killProcess(String pid, {ProcessManager processManager}) async {
  assert(pid != null, 'Must specify a pid to kill');
  processManager ??= const LocalProcessManager();
  ProcessResult result;
  if (Platform.isWindows) {
    result = await processManager.run(<String>[
      'taskkill.exe',
      '/pid',
      pid,
      '/f',
    ]);
  } else {
    result = await processManager.run(<String>[
      'kill',
      '-9',
      pid,
    ]);
  }
  return result.exitCode == 0;
}

Stream<RunningProcessInfo> getRunningProcesses({
  String processName,
  ProcessManager processManager,
}) {
  processManager ??= const LocalProcessManager();
  if (Platform.isWindows) {
    return windowsRunningProcesses(processName);
  }
  return posixRunningProcesses(processName, processManager);
}

@visibleForTesting
Stream<RunningProcessInfo> windowsRunningProcesses(String processName) async* {
  // PowerShell script to get the command line arguments and create time of
  // a process.
  // See: https://docs.microsoft.com/en-us/windows/desktop/cimwin32prov/win32-process
  final String script = processName != null
      ? '"Get-CimInstance Win32_Process -Filter \\\"name=\'$processName\'\\\" | Select-Object ProcessId,CreationDate,CommandLine | Format-Table -AutoSize | Out-String -Width 4096"'
      : '"Get-CimInstance Win32_Process | Select-Object ProcessId,CreationDate,CommandLine | Format-Table -AutoSize | Out-String -Width 4096"';
  // Unfortunately, there doesn't seem to be a good way to get ProcessManager to
  // run this. May be a bug in Dart.
  // TODO(dnfield): fix this when https://github.com/dart-lang/sdk/issues/36175 is resolved.
  final ProcessResult result = await Process.run(
    'powershell -command $script',
    <String>[],
  );
  if (result.exitCode != 0) {
    print('Could not list processes!');
    print(result.stderr);
    print(result.stdout);
    return;
  }
  for (RunningProcessInfo info in processPowershellOutput(result.stdout as String)) {
    yield info;
  }
}

/// Parses the output of the PowerShell script from [windowsRunningProcesses].
///
/// E.g.:
/// ProcessId CreationDate          CommandLine
/// --------- ------------          -----------
///      2904 3/11/2019 11:01:54 AM "C:\Program Files\Android\Android Studio\jre\bin\java.exe" -Xmx1536M -Dfile.encoding=windows-1252 -Duser.country=US -Duser.language=en -Duser.variant -cp C:\Users\win1\.gradle\wrapper\dists\gradle-4.10.2-all\9fahxiiecdb76a5g3aw9oi8rv\gradle-4.10.2\lib\gradle-launcher-4.10.2.jar org.gradle.launcher.daemon.bootstrap.GradleDaemon 4.10.2
@visibleForTesting
Iterable<RunningProcessInfo> processPowershellOutput(String output) sync* {
  if (output == null) {
    return;
  }

  const int processIdHeaderSize = 'ProcessId'.length;
  const int creationDateHeaderStart = processIdHeaderSize + 1;
  int creationDateHeaderEnd;
  int commandLineHeaderStart;
  bool inTableBody = false;
  for (String line in output.split('\n')) {
    if (line.startsWith('ProcessId')) {
      commandLineHeaderStart = line.indexOf('CommandLine');
      creationDateHeaderEnd = commandLineHeaderStart - 1;
    }
    if (line.startsWith('--------- ------------')) {
      inTableBody = true;
      continue;
    }
    if (!inTableBody || line.isEmpty) {
      continue;
    }
    if (line.length < commandLineHeaderStart) {
      continue;
    }

    // 3/11/2019 11:01:54 AM
    // 12/11/2019 11:01:54 AM
    String rawTime = line.substring(
      creationDateHeaderStart,
      creationDateHeaderEnd,
    ).trim();

    if (rawTime[1] == '/') {
      rawTime = '0$rawTime';
    }
    if (rawTime[4] == '/') {
      rawTime = rawTime.substring(0, 3) + '0' + rawTime.substring(3);
    }
    final String year = rawTime.substring(6, 10);
    final String month = rawTime.substring(3, 5);
    final String day = rawTime.substring(0, 2);
    String time = rawTime.substring(11, 19);
    if (time[7] == ' ') {
      time = '0$time'.trim();
    }
    if (rawTime.endsWith('PM')) {
      final int hours = int.parse(time.substring(0, 2));
      time = '${hours + 12}${time.substring(2)}';
    }

    final String pid = line.substring(0, processIdHeaderSize).trim();
    final DateTime creationDate = DateTime.parse('$year-$month-${day}T$time');
    final String commandLine = line.substring(commandLineHeaderStart).trim();
    yield RunningProcessInfo(pid, creationDate, commandLine);
  }
}

@visibleForTesting
Stream<RunningProcessInfo> posixRunningProcesses(
  String processName,
  ProcessManager processManager,
) async* {
  // Cirrus is missing this in Linux for some reason.
  if (!processManager.canRun('ps')) {
    print('Cannot list processes on this system: `ps` not available.');
    return;
  }
  final ProcessResult result = await processManager.run(<String>[
    'ps',
    '-eo',
    'lstart,pid,command',
  ]);
  if (result.exitCode != 0) {
    print('Could not list processes!');
    print(result.stderr);
    print(result.stdout);
    return;
  }
  for (RunningProcessInfo info in processPsOutput(result.stdout as String, processName)) {
    yield info;
  }
}

/// Parses the output of the command in [posixRunningProcesses].
///
/// E.g.:
///
/// STARTED                        PID COMMAND
/// Sat Mar  9 20:12:47 2019         1 /sbin/launchd
/// Sat Mar  9 20:13:00 2019        49 /usr/sbin/syslogd
@visibleForTesting
Iterable<RunningProcessInfo> processPsOutput(
  String output,
  String processName,
) sync* {
  if (output == null) {
    return;
  }
  bool inTableBody = false;
  for (String line in output.split('\n')) {
    if (line.trim().startsWith('STARTED')) {
      inTableBody = true;
      continue;
    }
    if (!inTableBody || line.isEmpty) {
      continue;
    }

    if (processName != null && !line.contains(processName)) {
      continue;
    }
    if (line.length < 25) {
      continue;
    }

    // 'Sat Feb 16 02:29:55 2019'
    // 'Sat Mar  9 20:12:47 2019'
    const Map<String, String> months = <String, String>{
      'Jan': '01',
      'Feb': '02',
      'Mar': '03',
      'Apr': '04',
      'May': '05',
      'Jun': '06',
      'Jul': '07',
      'Aug': '08',
      'Sep': '09',
      'Oct': '10',
      'Nov': '11',
      'Dec': '12',
    };
    final String rawTime = line.substring(0, 24);

    final String year = rawTime.substring(20, 24);
    final String month = months[rawTime.substring(4, 7)];
    final String day = rawTime.substring(8, 10).replaceFirst(' ', '0');
    final String time = rawTime.substring(11, 19);

    final DateTime creationDate = DateTime.parse('$year-$month-${day}T$time');
    line = line.substring(24).trim();
    final int nextSpace = line.indexOf(' ');
    final String pid = line.substring(0, nextSpace);
    final String commandLine = line.substring(nextSpace + 1);
    yield RunningProcessInfo(pid, creationDate, commandLine);
  }
}
