// Copyright (c) 2017, 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 'package:analyzer/analyzer.dart';
import 'package:path/path.dart' as p;
import 'package:collection/collection.dart';
import 'package:pub/src/dart.dart';
import 'package:pub/src/entrypoint.dart';
import 'package:pub/src/io.dart';
import 'package:pub/src/log.dart' as log;
import 'package:pub/src/utils.dart';
import 'package:pub/src/validator.dart';
import 'package:source_span/source_span.dart';
import 'package:stack_trace/stack_trace.dart';

/// Validates that Dart source files only import declared dependencies.
class StrictDependenciesValidator extends Validator {
  StrictDependenciesValidator(Entrypoint entrypoint) : super(entrypoint);

  /// Lazily returns all dependency uses in [files].
  ///
  /// Files that do not parse and directives that don't import or export
  /// `package:` URLs are ignored.
  Iterable<_Usage> _findPackages(Iterable<String> files) sync* {
    for (var file in files) {
      List<UriBasedDirective> directives;
      var contents = readTextFile(file);
      try {
        directives = parseImportsAndExports(contents, name: file);
      } on AnalyzerErrorGroup catch (e, s) {
        // Ignore files that do not parse.
        log.fine(getErrorMessage(e));
        log.fine(new Chain.forTrace(s).terse);
        continue;
      }

      for (var directive in directives) {
        Uri url;
        try {
          url = Uri.parse(directive.uri.stringValue);
        } on FormatException catch (_) {
          // Ignore a format exception. [url] will be null, and we'll emit an
          // "Invalid URL" warning below.
        }

        // If the URL could not be parsed or it is a `package:` URL AND there
        // are no segments OR any segment are empty, it's invalid.
        if (url == null ||
            (url.scheme == 'package' &&
                (url.pathSegments.length < 2 ||
                    url.pathSegments.any((s) => s.isEmpty)))) {
          warnings.add(
              _Usage.errorMessage('Invalid URL.', file, contents, directive));
        } else if (url.scheme == 'package') {
          yield new _Usage(file, contents, directive, url);
        }
      }
    }
  }

  Future validate() async {
    var dependencies = entrypoint.root.dependencies.keys.toSet()
      ..add(entrypoint.root.name);
    var devDependencies = new MapKeySet(entrypoint.root.devDependencies);
    _validateLibBin(dependencies, devDependencies);
    _validateBenchmarkExampleTestTool(dependencies, devDependencies);
  }

  /// Validates that no Dart files in `lib/` or `bin/` have dependencies that
  /// aren't in [deps].
  ///
  /// The [devDeps] are used to generate special warnings for files that import
  /// dev dependencies.
  void _validateLibBin(Set<String> deps, Set<String> devDeps) {
    for (var usage in _usagesBeneath(['lib', 'bin'])) {
      if (!deps.contains(usage.package)) {
        if (devDeps.contains(usage.package)) {
          warnings.add(usage.dependencyMisplaceMessage());
        } else {
          warnings.add(usage.dependencyMissingMessage());
        }
      }
    }
  }

  /// Validates that no Dart files in `benchmark/`, `example/, `test/` or
  /// `tool/` have dependencies that aren't in [deps] or [devDeps].
  void _validateBenchmarkExampleTestTool(
      Set<String> deps, Set<String> devDeps) {
    for (var usage
        in _usagesBeneath(['benchmark', 'example', 'test', 'tool'])) {
      if (!deps.contains(usage.package) && !devDeps.contains(usage.package)) {
        warnings.add(usage.dependencyMissingMessage());
      }
    }
  }

  Iterable<_Usage> _usagesBeneath(List<String> paths) => _findPackages(paths
      .map((path) => entrypoint.root.listFiles(beneath: path))
      .expand((files) => files)
      .where((String file) => p.extension(file) == '.dart'));
}

/// A parsed import or export directive in a D source file.
class _Usage {
  /// Returns a formatted error message highlighting [directive] in [file].
  static String errorMessage(String message, String file, String contents,
      UriBasedDirective directive) {
    return new SourceFile.fromString(contents, url: file)
        .span(directive.offset, directive.offset + directive.length)
        .message(message);
  }

  /// The path to the file from which [_directive] was parsed.
  final String _file;

  /// The contents of [_file].
  final String _contents;

  /// The URI parsed from [_directive].
  final Uri _url;

  /// The directive that uses [_url].
  final UriBasedDirective _directive;

  _Usage(this._file, this._contents, this._directive, this._url);

  /// The name of the package referred to by this usage..
  String get package => _url.pathSegments.first;

  /// Returns a message associated with [_directive].
  ///
  /// We assume that normally all directives are valid and we won't see an error
  /// message, so we create the SourceFile lazily to avoid parsing line endings
  /// in the case of only valid directives.
  String _toMessage(String message) =>
      errorMessage(message, _file, _contents, _directive);

  /// Returns an error message saying the package is not listed in dependencies.
  String dependencyMissingMessage() =>
      _toMessage("This package doesn't depend on $package.");

  /// Returns an error message saying the package should be in `dependencies`.
  String dependencyMisplaceMessage() {
    var shortFile = p.split(p.relative(_file)).first;
    return _toMessage(
        '$package is a dev dependency. Packages used in $shortFile/ must be '
        'declared as normal dependencies.');
  }
}
