// Copyright (c) 2014, 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:collection';
import 'dart:convert';

import '../ascii_tree.dart' as tree;
import '../command.dart';
import '../command_runner.dart';
import '../log.dart' as log;
import '../package.dart';
import '../sdk.dart';
import '../utils.dart';

/// Handles the `deps` pub command.
class DepsCommand extends PubCommand {
  @override
  String get name => 'deps';

  @override
  String get description => 'Print package dependencies.';

  @override
  String get argumentsDescription => '[arguments...]';

  @override
  String get docUrl => 'https://dart.dev/tools/pub/cmd/pub-deps';

  @override
  bool get takesArguments => false;

  /// The [StringBuffer] used to accumulate the output.
  // TODO(sigurdm): use a local variable for this.
  final _buffer = StringBuffer();

  /// Whether to include dev dependencies.
  bool get _includeDev => argResults['dev'];

  DepsCommand() {
    argParser.addOption(
      'style',
      abbr: 's',
      help: 'How output should be displayed.',
      allowed: ['compact', 'tree', 'list'],
      defaultsTo: 'tree',
    );

    argParser.addFlag(
      'dev',
      help: 'Whether to include dev dependencies.',
      defaultsTo: true,
    );

    argParser.addFlag(
      'executables',
      negatable: false,
      help: 'List all available executables.',
    );

    argParser.addFlag(
      'json',
      negatable: false,
      help: 'Output dependency information in a json format.',
    );

    argParser.addOption(
      'directory',
      abbr: 'C',
      help: 'Run this in the directory<dir>.',
      valueHelp: 'dir',
    );
  }

  @override
  Future<void> runProtected() async {
    // Explicitly Run this in the directorycase we don't access `entrypoint.packageGraph`.
    entrypoint.assertUpToDate();
    _buffer.clear();

    if (argResults['json']) {
      if (argResults.wasParsed('dev')) {
        usageException(
          'Cannot combine --json and --dev.\nThe json output contains the dependency type in the output.',
        );
      }
      if (argResults.wasParsed('executables')) {
        usageException(
          'Cannot combine --json and --executables.\nThe json output always lists available executables.',
        );
      }
      if (argResults.wasParsed('style')) {
        usageException('Cannot combine --json and --style.');
      }
      final visited = <String>[];
      final toVisit = [entrypoint.root.name];
      final packagesJson = <dynamic>[];
      while (toVisit.isNotEmpty) {
        final current = toVisit.removeLast();
        if (visited.contains(current)) continue;
        visited.add(current);
        final currentPackage = entrypoint.packageGraph.packages[current]!;
        final next = (current == entrypoint.root.name
                ? entrypoint.root.immediateDependencies
                : currentPackage.dependencies)
            .keys
            .toList();
        final dependencyType = entrypoint.root.dependencyType(current);
        final kind = currentPackage == entrypoint.root
            ? 'root'
            : (dependencyType == DependencyType.direct
                ? 'direct'
                : (dependencyType == DependencyType.dev
                    ? 'dev'
                    : 'transitive'));
        final source =
            entrypoint.lockFile.packages[current]?.source.name ?? 'root';
        packagesJson.add({
          'name': current,
          'version': currentPackage.version.toString(),
          'kind': kind,
          'source': source,
          'dependencies': next
        });
        toVisit.addAll(next);
      }
      var executables = [
        for (final package in [
          entrypoint.root,
          ...entrypoint.root.immediateDependencies.keys
              .map((name) => entrypoint.packageGraph.packages[name])
        ])
          ...package!.executableNames.map(
            (name) => package == entrypoint.root
                ? ':$name'
                : (package.name == name ? name : '${package.name}:$name'),
          )
      ];

      _buffer.writeln(
        JsonEncoder.withIndent('  ').convert(
          {
            'root': entrypoint.root.name,
            'packages': packagesJson,
            'sdks': [
              for (var sdk in sdks.values)
                if (sdk.version != null)
                  {'name': sdk.name, 'version': sdk.version.toString()}
            ],
            'executables': executables
          },
        ),
      );
    } else {
      if (argResults['executables']) {
        _outputExecutables();
      } else {
        for (var sdk in sdks.values) {
          if (!sdk.isAvailable) continue;
          _buffer.writeln("${log.bold('${sdk.name} SDK')} ${sdk.version}");
        }

        _buffer.writeln(_labelPackage(entrypoint.root));

        switch (argResults['style']) {
          case 'compact':
            _outputCompact();
            break;
          case 'list':
            _outputList();
            break;
          case 'tree':
            _outputTree();
            break;
        }
      }
    }

    log.message(_buffer);
  }

  /// Outputs a list of all of the package's immediate, dev, override, and
  /// transitive dependencies.
  ///
  /// For each dependency listed, *that* package's immediate dependencies are
  /// shown. Unlike [_outputList], this prints all of these dependencies on one
  /// line.
  void _outputCompact() {
    var root = entrypoint.root;
    _outputCompactPackages('dependencies', root.dependencies.keys);
    if (_includeDev) {
      _outputCompactPackages('dev dependencies', root.devDependencies.keys);
    }
    _outputCompactPackages(
      'dependency overrides',
      root.dependencyOverrides.keys,
    );

    var transitive = _getTransitiveDependencies();
    _outputCompactPackages('transitive dependencies', transitive);
  }

  /// Outputs one section of packages in the compact output.
  void _outputCompactPackages(String section, Iterable<String> names) {
    if (names.isEmpty) return;

    _buffer.writeln();
    _buffer.writeln('$section:');
    for (var name in ordered(names)) {
      var package = _getPackage(name);

      _buffer.write('- ${_labelPackage(package)}');
      if (package.dependencies.isEmpty) {
        _buffer.writeln();
      } else {
        var depNames = package.dependencies.keys;
        var depsList = "[${depNames.join(' ')}]";
        _buffer.writeln(' ${log.gray(depsList)}');
      }
    }
  }

  /// Outputs a list of all of the package's immediate, dev, override, and
  /// transitive dependencies.
  ///
  /// For each dependency listed, *that* package's immediate dependencies are
  /// shown.
  void _outputList() {
    var root = entrypoint.root;
    _outputListSection('dependencies', root.dependencies.keys);
    if (_includeDev) {
      _outputListSection('dev dependencies', root.devDependencies.keys);
    }
    _outputListSection('dependency overrides', root.dependencyOverrides.keys);

    var transitive = _getTransitiveDependencies();
    if (transitive.isEmpty) return;

    _outputListSection('transitive dependencies', ordered(transitive));
  }

  /// Outputs one section of packages in the list output.
  void _outputListSection(String name, Iterable<String> deps) {
    if (deps.isEmpty) return;

    _buffer.writeln();
    _buffer.writeln('$name:');

    for (var name in deps) {
      var package = _getPackage(name);
      _buffer.writeln('- ${_labelPackage(package)}');

      for (var dep in package.dependencies.values) {
        _buffer
            .writeln('  - ${log.bold(dep.name)} ${log.gray(dep.constraint)}');
      }
    }
  }

  /// Generates a dependency tree for the root package.
  ///
  /// If a package is encountered more than once (i.e. a shared or circular
  /// dependency), later ones are not traversed. This is done in breadth-first
  /// fashion so that a package will always be expanded at the shallowest
  /// depth that it appears at.
  void _outputTree() {
    // The work list for the breadth-first traversal. It contains the package
    // being added to the tree, and the parent map that will receive that
    // package.
    var toWalk = Queue<Pair<Package, Map<String, Map>>>();
    var visited = <String>{entrypoint.root.name};

    // Start with the root dependencies.
    var packageTree = <String, Map>{};
    var immediateDependencies =
        entrypoint.root.immediateDependencies.keys.toSet();
    if (!_includeDev) {
      immediateDependencies.removeAll(entrypoint.root.devDependencies.keys);
    }
    for (var name in immediateDependencies) {
      toWalk.add(Pair(_getPackage(name), packageTree));
    }

    // Do a breadth-first walk to the dependency graph.
    while (toWalk.isNotEmpty) {
      var pair = toWalk.removeFirst();
      var package = pair.first;
      var map = pair.last;

      if (visited.contains(package.name)) {
        map[log.gray('${package.name}...')] = <String, Map>{};
        continue;
      }

      visited.add(package.name);

      // Populate the map with this package's dependencies.
      var childMap = <String, Map>{};
      map[_labelPackage(package)] = childMap;

      for (var dep in package.dependencies.values) {
        toWalk.add(Pair(_getPackage(dep.name), childMap));
      }
    }

    _buffer.write(tree.fromMap(packageTree));
  }

  String _labelPackage(Package package) =>
      '${log.bold(package.name)} ${package.version}';

  /// Gets the names of the non-immediate dependencies of the root package.
  Set<String> _getTransitiveDependencies() {
    var transitive = _getAllDependencies();
    var root = entrypoint.root;
    transitive.remove(root.name);
    transitive.removeAll(root.dependencies.keys);
    if (_includeDev) {
      transitive.removeAll(root.devDependencies.keys);
    }
    transitive.removeAll(root.dependencyOverrides.keys);
    return transitive;
  }

  Set<String> _getAllDependencies() {
    if (_includeDev) return entrypoint.packageGraph.packages.keys.toSet();

    var nonDevDependencies = entrypoint.root.dependencies.keys.toList()
      ..addAll(entrypoint.root.dependencyOverrides.keys);
    return nonDevDependencies
        .expand((name) => entrypoint.packageGraph.transitiveDependencies(name))
        .map((package) => package.name)
        .toSet();
  }

  /// Get the package named [name], or throw a [DataError] if it's not
  /// available.
  ///
  /// It's very unlikely that the lockfile won't be up-to-date with the pubspec,
  /// but it's possible, since [Entrypoint.assertUpToDate]'s modification time
  /// check can return a false negative. This fails gracefully if that happens.
  Package _getPackage(String name) {
    var package = entrypoint.packageGraph.packages[name];
    if (package != null) return package;
    dataError('The pubspec.yaml file has changed since the pubspec.lock file '
        'was generated, please run "$topLevelProgram pub get" again.');
  }

  /// Outputs all executables reachable from [entrypoint].
  void _outputExecutables() {
    var packages = [
      entrypoint.root,
      ...(_includeDev
              ? entrypoint.root.immediateDependencies
              : entrypoint.root.dependencies)
          .keys
          .map((name) => entrypoint.packageGraph.packages[name]!)
    ];

    for (var package in packages) {
      var executables = package.executableNames;
      if (executables.isNotEmpty) {
        _buffer.writeln(_formatExecutables(package.name, executables.toList()));
      }
    }
  }

  /// Returns formatted string that lists [executables] for the [packageName].
  /// Examples:
  ///
  ///     _formatExecutables('foo', ['foo'])        // -> 'foo'
  ///     _formatExecutables('foo', ['bar'])        // -> 'foo:bar'
  ///     _formatExecutables('foo', ['bar', 'foo']) // -> 'foo: foo, bar'
  ///
  /// Note the leading space before first executable and sorting order in the
  /// last example.
  String _formatExecutables(String packageName, List<String> executables) {
    if (executables.length == 1) {
      // If executable matches the package name omit the name of executable in
      // the output.
      return executables.first != packageName
          ? '$packageName:${log.bold(executables.first)}'
          : log.bold(executables.first);
    }

    // Sort executables to make executable that matches the package name to be
    // the first in the list.
    executables.sort((e1, e2) {
      if (e1 == packageName) {
        return -1;
      } else if (e2 == packageName) {
        return 1;
      } else {
        return e1.compareTo(e2);
      }
    });

    return '$packageName: ${executables.map(log.bold).join(', ')}';
  }
}
