// 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 'package:analyzer/analyzer.dart' as analyzer;
import 'package:path/path.dart' as p;

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

/// Returns `true` if [path] looks like a Dart entrypoint.
bool _isDartExecutable(String path) {
  try {
    var unit = analyzer.parseDartFile(path, parseFunctionBodies: false);
    return isEntrypoint(unit);
  } on analyzer.AnalyzerErrorGroup {
    return false;
  }
}

/// Handles the `deps` pub command.
class DepsCommand extends PubCommand {
  String get name => "deps";
  String get description => "Print package dependencies.";
  List<String> get aliases => const ["dependencies", "tab"];
  String get invocation => "pub deps";
  String get docUrl => "http://dartlang.org/tools/pub/cmd/pub-deps.html";
  bool get takesArguments => false;

  /// The [StringBuffer] used to accumulate the output.
  StringBuffer _buffer;

  /// 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",
        negatable: true,
        help: "Whether to include dev dependencies.",
        defaultsTo: true);

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

  void run() {
    // Explicitly run this in case we don't access `entrypoint.packageGraph`.
    entrypoint.assertUpToDate();

    _buffer = new StringBuffer();

    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.
  _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.
  _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 = new Queue<Pair<Package, Map<String, Map>>>();
    var visited = new Set<String>.from([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(new 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(new Pair(_getPackage(dep.name), childMap));
      }
    }

    _buffer.write(tree.fromMap(packageTree, showAllChildren: true));
  }

  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 "pub get" again.');
    return null;
  }

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

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

  /// Lists all Dart files in the `bin` directory of the [package].
  ///
  /// Returns file names without extensions.
  Iterable<String> _getExecutablesFor(Package package) =>
      package.executablePaths
          .where((e) => _isDartExecutable(p.absolute(package.dir, e)))
          .map((e) => p.basenameWithoutExtension(e));

  /// 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(', ')}';
  }
}
