// Copyright (c) 2016, 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/dart/ast/ast.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/dart/scanner/reader.dart';
import 'package:analyzer/src/generated/parser.dart';
import 'package:front_end/file_system.dart';
import 'package:front_end/src/async_dependency_walker.dart';
import 'package:front_end/src/base/uri_resolver.dart';
import 'package:front_end/src/scanner/scanner.dart';
import 'package:package_config/packages_file.dart' as package_config;

import 'compiler_options.dart';

/// Generates a representation of the dependency graph of a program.
///
/// Given the Uri of one or more files, this function follows `import`,
/// `export`, and `part` declarations to discover a graph of all files involved
/// in the program.
Future<Graph> graphForProgram(
    List<Uri> sources, CompilerOptions options) async {
  Map<String, Uri> packages;
  if (options.packagesFilePath == null) {
    throw new UnimplementedError(); // TODO(paulberry): search for .packages
  } else if (options.packagesFilePath.isEmpty) {
    packages = {};
  } else {
    var contents = await options.fileSystem
        .entityForPath(options.packagesFilePath)
        .readAsBytes();
    var baseLocation =
        options.fileSystem.context.toUri(options.packagesFilePath);
    packages = package_config.parse(contents, baseLocation);
  }
  var sdkLibraries = <String, Uri>{}; // TODO(paulberry): support SDK libraries
  var uriResolver =
      new UriResolver(packages, sdkLibraries, options.fileSystem.context);
  var walker = new _Walker(options.fileSystem, uriResolver, options.compileSdk);
  var startingPoint = new _StartingPoint(walker, sources);
  await walker.walk(startingPoint);
  return walker.graph;
}

/// A representation of the dependency graph of a program.
///
/// Not intended to be extended, implemented, or mixed in by clients.
class Graph {
  /// A list of all library cycles in the program, in topologically sorted order
  /// (each cycle only depends on libraries in the cycles that precede it).
  final topologicallySortedCycles = <LibraryCycleNode>[];

  Graph._();
}

/// A representation of a single library cycle in the dependency graph of a
/// program.
///
/// Not intended to be extended, implemented, or mixed in by clients.
class LibraryCycleNode {
  /// A map of all the libraries in the cycle, keyed by the URI of their
  /// defining compilation unit.
  final libraries = <Uri, LibraryNode>{};

  LibraryCycleNode._();
}

/// A representation of a single library in the dependency graph of a program.
///
/// Not intended to be extended, implemented, or mixed in by clients.
class LibraryNode {
  /// The URI of this library's defining compilation unit.
  final Uri uri;

  /// A list of the URIs of all of this library's "part" files.
  final parts = <Uri>[];

  /// A list of all the other libraries this library directly depends on.
  final dependencies = <LibraryNode>[];

  LibraryNode._(this.uri);
}

class _Scanner extends Scanner {
  _Scanner(String contents) : super(new CharSequenceReader(contents)) {
    preserveComments = false;
  }

  @override
  void reportError(errorCode, int offset, List<Object> arguments) {
    // TODO(paulberry): report errors.
  }
}

class _StartingPoint extends _WalkerNode {
  final List<Uri> sources;

  _StartingPoint(_Walker walker, this.sources) : super(walker, null);

  @override
  Future<List<_WalkerNode>> computeDependencies() async =>
      sources.map(walker.nodeForUri).toList();
}

class _Walker extends AsyncDependencyWalker<_WalkerNode> {
  final FileSystem fileSystem;
  final UriResolver uriResolver;
  final _nodesByUri = <Uri, _WalkerNode>{};
  final graph = new Graph._();
  final bool compileSdk;

  _Walker(this.fileSystem, this.uriResolver, this.compileSdk);

  @override
  Future<Null> evaluate(_WalkerNode v) {
    if (v is _StartingPoint) return new Future.value();
    return evaluateScc([v]);
  }

  @override
  Future<Null> evaluateScc(List<_WalkerNode> scc) {
    var cycle = new LibraryCycleNode._();
    for (var walkerNode in scc) {
      cycle.libraries[walkerNode.uri] = walkerNode.library;
    }
    graph.topologicallySortedCycles.add(cycle);
    return new Future.value();
  }

  _WalkerNode nodeForUri(Uri referencedUri) {
    var dependencyNode = _nodesByUri.putIfAbsent(
        referencedUri, () => new _WalkerNode(this, referencedUri));
    return dependencyNode;
  }
}

class _WalkerNode extends Node<_WalkerNode> {
  static final dartCoreUri = Uri.parse('dart:core');
  final _Walker walker;
  final Uri uri;
  final LibraryNode library;

  _WalkerNode(this.walker, Uri uri)
      : uri = uri,
        library = new LibraryNode._(uri);

  @override
  Future<List<_WalkerNode>> computeDependencies() async {
    var dependencies = <_WalkerNode>[];
    // TODO(paulberry): add error recovery if the file can't be read.
    var path = walker.uriResolver.resolve(uri);
    if (path == null) {
      // TODO(paulberry): If an error reporter was provided, report the error
      // in the proper way and continue.
      throw new StateError('Invalid URI: $uri');
    }
    var contents = await walker.fileSystem.entityForPath(path).readAsString();
    var scanner = new _Scanner(contents);
    var token = scanner.tokenize();
    // TODO(paulberry): report errors.
    var parser = new Parser(null, AnalysisErrorListener.NULL_LISTENER);
    var unit = parser.parseDirectives(token);
    bool coreUriFound = false;
    void handleDependency(Uri referencedUri) {
      _WalkerNode dependencyNode = walker.nodeForUri(referencedUri);
      library.dependencies.add(dependencyNode.library);
      if (referencedUri.scheme != 'dart' || walker.compileSdk) {
        dependencies.add(dependencyNode);
      }
      if (referencedUri == dartCoreUri) {
        coreUriFound = true;
      }
    }

    for (var directive in unit.directives) {
      if (directive is UriBasedDirective) {
        // TODO(paulberry): when we support SDK libraries, we'll need more
        // complex logic here to find SDK parts correctly.
        var referencedUri = uri.resolve(directive.uri.stringValue);
        if (directive is PartDirective) {
          library.parts.add(referencedUri);
        } else {
          handleDependency(referencedUri);
        }
      }
    }
    if (!coreUriFound) {
      handleDependency(dartCoreUri);
    }
    return dependencies;
  }
}
