// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. 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 'dart:convert';
import 'dart:io';

import 'package:analysis_server/src/utilities/process.dart';
import 'package:analyzer/instrumentation/service.dart';
import 'package:path/path.dart' as path;

/// A class for interacting with the `pub` command.
///
/// `pub` commands will be queued and not run concurrently.
class PubCommand {
  static const String _pubEnvironmentKey = 'PUB_ENVIRONMENT';

  /// An environment variable that can be set to prevent a [PubCommand] from
  /// being created/used by the analysis server.
  ///
  /// This is generally intended for integration tests to prevent them spawning
  /// pub commands while testing other functionality.
  static const String disablePubCommandEnvironmentKey =
      'DART_SERVER_DISABLE_PUB_COMMAND';

  final InstrumentationService _instrumentationService;
  late final ProcessRunner _processRunner;
  late final String _pubEnvironmentValue;

  /// Active processes that should be killed when shutting down.
  final _activeProcesses = <Process>{};

  /// Tracks the last queued command to avoid overlapping because pub does not
  /// do its own locking when accessing the cache.
  ///
  /// https://github.com/dart-lang/pub/issues/1178
  ///
  /// This does not prevent running concurrently with commands spawned by other
  /// tools (such as the IDE).
  var _lastQueuedCommand = Future<void>.value();

  PubCommand(this._instrumentationService, this._processRunner) {
    // When calling the `pub` command, we must add an identifier to the
    // PUB_ENVIRONMENT environment variable (joined with colons).
    const pubEnvString = 'analysis_server.pub_api';
    final existingPubEnv = Platform.environment[_pubEnvironmentKey];
    _pubEnvironmentValue = [
      if (existingPubEnv?.isNotEmpty ?? false) existingPubEnv,
      pubEnvString,
    ].join(':');
  }

  /// Runs `pub outdated --show-all` and returns the results.
  ///
  /// If any error occurs executing the command, returns an empty list.
  Future<List<PubOutdatedPackageDetails>> outdatedVersions(
      String pubspecPath) async {
    final packageDirectory = path.dirname(pubspecPath);
    final result = await _runPubJsonCommand(
        ['outdated', '--show-all', '--json'],
        workingDirectory: packageDirectory);

    if (result == null) {
      return [];
    }

    final packages =
        (result['packages'] as List<dynamic>?)?.cast<Map<String, Object?>>();
    if (packages == null) {
      return [];
    }

    return packages
        .map(
          (json) => PubOutdatedPackageDetails(
            json['package'] as String,
            currentVersion: _version(json, 'current'),
            latestVersion: _version(json, 'latest'),
            resolvableVersion: _version(json, 'resolvable'),
            upgradableVersion: _version(json, 'upgradable'),
          ),
        )
        .toList();
  }

  /// Terminates any in-process commands with [ProcessSignal.sigterm].
  void shutdown() {
    for (var process in _activeProcesses) {
      _instrumentationService.logInfo('Terminating process ${process.pid}');
      process.kill();
    }
  }

  /// Runs a pub command and decodes JSON from `stdout`.
  ///
  /// Returns null if:
  ///   - exit code is non-zero
  ///   - returned text cannot be decoded as JSON
  Future<Map<String, Object?>?> _runPubJsonCommand(List<String> args,
      {required String workingDirectory}) async {
    // Atomically replace the lastQueuedCommand future with our own to ensure
    // only one command waits on any previous commands future.
    final completer = Completer<void>();
    final lastCommand = _lastQueuedCommand;
    _lastQueuedCommand = completer.future;
    // And wait for that previous command to finish.
    await lastCommand.catchError((_) {});

    try {
      _instrumentationService.logInfo('Starting pub command $args');
      final process = await _processRunner.start(
          Platform.resolvedExecutable, ['pub', ...args],
          workingDirectory: workingDirectory,
          environment: {_pubEnvironmentKey: _pubEnvironmentValue});
      _activeProcesses.add(process);

      final exitCode = await process.exitCode;
      _activeProcesses.remove(process);
      final stdout = await process.stdout.transform(utf8.decoder).join();
      final stderr = await process.stderr.transform(utf8.decoder).join();

      if (exitCode != 0) {
        _instrumentationService
            .logError('pub command returned $exitCode exit code: $stderr.');
        return null;
      }

      try {
        final results = jsonDecode(stdout);
        _instrumentationService.logInfo('pub command completed successfully');
        return results as Map<String, Object?>?;
      } catch (e) {
        _instrumentationService
            .logError('pub command returned invalid JSON: $e.');
        return null;
      }
    } catch (e) {
      _instrumentationService.logError('pub command failed to run: $e.');
      return null;
    } finally {
      completer.complete();
    }
  }

  String? _version(Map<String, Object?> json, String type) {
    final versionType = json[type] as Map<String, Object?>?;
    final version =
        versionType != null ? versionType['version'] as String? : null;
    return version;
  }
}

class PubOutdatedPackageDetails {
  final String packageName;
  final String? currentVersion;
  final String? latestVersion;
  final String? resolvableVersion;
  final String? upgradableVersion;

  PubOutdatedPackageDetails(
    this.packageName, {
    required this.currentVersion,
    required this.latestVersion,
    required this.resolvableVersion,
    required this.upgradableVersion,
  });
}
