// Copyright (c) 2013, 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.

/// A library for compiling Dart code and manipulating analyzer parse trees.
import 'dart:async';
import 'dart:io';

import 'package:analyzer/dart/analysis/analysis_context.dart';
import 'package:analyzer/dart/analysis/context_builder.dart';
import 'package:analyzer/dart/analysis/context_locator.dart';
import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/error/error.dart';
import 'package:path/path.dart' as p;

import 'exceptions.dart';
import 'io.dart';
import 'log.dart' as log;
import 'utils.dart';

/// Returns whether [dart] looks like an entrypoint file.
bool isEntrypoint(CompilationUnit dart) {
  // Allow two or fewer arguments so that entrypoints intended for use with
  // [spawnUri] get counted.
  //
  // TODO(nweiz): this misses the case where a Dart file doesn't contain main(),
  // but it parts in another file that does.
  return dart.declarations.any((node) {
    return node is FunctionDeclaration &&
        node.name.name == "main" &&
        node.functionExpression.parameters.parameters.length <= 2;
  });
}

/// Snapshots the Dart executable at [executableUrl] to a snapshot at
/// [snapshotPath].
///
/// If [packagesFile] is passed, it's used to resolve `package:` URIs in the
/// executable. Otherwise, a `packages/` directory or a package spec is inferred
/// from the executable's location.
///
/// If [name] is passed, it is used to describe the executable in logs and error
/// messages.
///
/// When running in Dart 2 mode, this automatically creates a Dart 2-compatible
/// snapshot as well at `$snapshotPath.dart2`.
Future snapshot(Uri executableUrl, String snapshotPath,
    {Uri packagesFile, String name}) async {
  name = log.bold(name ?? executableUrl.toString());

  var dart1Args = [
    '--no-preview-dart-2',
    '--snapshot=$snapshotPath',
    executableUrl.toString()
  ];

  var dart2Path = '$snapshotPath.dart2';
  var dart2Args =
      isDart2 ? ['--snapshot=$dart2Path', executableUrl.toString()] : null;

  if (packagesFile != null) {
    dart1Args.insert(0, "--packages=$packagesFile");

    // Resolve [packagesFile] in case it's relative to work around sdk#33177.
    dart2Args?.insert(0, "--packages=${Uri.base.resolveUri(packagesFile)}");
  }

  var processes = [runProcess(Platform.executable, dart1Args)];
  if (isDart2) processes.add(runProcess(Platform.executable, dart2Args));
  var results = await Future.wait(processes);

  var failure =
      results.firstWhere((result) => !result.success, orElse: () => null);
  if (failure == null) {
    log.message("Precompiled $name.");
  } else {
    // Don't leave partial results.
    deleteEntry(snapshotPath);
    deleteEntry(dart2Path);

    throw new ApplicationException(log.yellow("Failed to precompile $name:\n") +
        failure.stderr.join('\n'));
  }
}

class AnalysisContextManager {
  /// The map from a context root directory to to the context.
  final Map<String, AnalysisContext> _contexts = {};

  /// Ensure that there are analysis contexts for the directory with the
  /// given [path]. If any previously added root covers the [path], keep
  /// the previously created analysis context.
  ///
  /// This method does not discover analysis roots "up", it only looks down
  /// the given [path]. It is expected that the client knows analysis roots
  /// in advance. Pub does know, it is the packages it works with.
  void createContextsForDirectory(String path) {
    _throwIfNotAbsolutePath(path);

    // We add all contexts below the given directory.
    // So, children contexts must also have been added.
    if (_contexts.containsKey(path)) {
      return;
    }

    // Add new contexts for the given path.
    var contextLocator = new ContextLocator();
    var roots = contextLocator.locateRoots(includedPaths: [path]);
    for (var root in roots) {
      String contextRootPath = root.root.path;

      // If there is already a context for this context root path, keep it.
      if (_contexts.containsKey(contextRootPath)) {
        continue;
      }

      var contextBuilder = new ContextBuilder();
      var context = contextBuilder.createContext(contextRoot: root);
      _contexts[contextRootPath] = context;
    }
  }

  /// Parse the file with the given [path] into AST.
  ///
  /// One of the containing directories must be used to create analysis
  /// contexts using [createContextsForDirectory]. Throws [StateError] if
  /// this has not been done.
  ///
  /// Throws [AnalyzerErrorGroup] is the file has parsing errors.
  CompilationUnit parse(String path) {
    var parseResult = _getExistingSession(path).getParsedAstSync(path);
    if (parseResult.errors.isNotEmpty) {
      throw new AnalyzerErrorGroup(parseResult.errors);
    }
    return parseResult.unit;
  }

  /// Return import and export directives in the file with the given [path].
  ///
  /// One of the containing directories must be used to create analysis
  /// contexts using [createContextsForDirectory]. Throws [StateError] if
  /// this has not been done.
  ///
  /// Throws [AnalyzerErrorGroup] is the file has parsing errors.
  List<UriBasedDirective> parseImportsAndExports(String path) {
    var unit = parse(path);
    var uriDirectives = <UriBasedDirective>[];
    for (var directive in unit.directives) {
      if (directive is UriBasedDirective) {
        uriDirectives.add(directive);
      }
    }
    return uriDirectives;
  }

  AnalysisSession _getExistingSession(String path) {
    _throwIfNotAbsolutePath(path);

    for (var context in _contexts.values) {
      if (context.contextRoot.isAnalyzed(path)) {
        return context.currentSession;
      }
    }

    throw new StateError('Unable to find the context to $path');
  }

  /// The driver supports only absolute paths, this method is used to validate
  /// any input paths to prevent errors later.
  void _throwIfNotAbsolutePath(String path) {
    if (!p.isAbsolute(path)) {
      throw new ArgumentError('Only absolute paths are supported: $path');
    }
  }
}

/// An error class that contains multiple [AnalysisError]s.
class AnalyzerErrorGroup implements Exception {
  final List<AnalysisError> errors;

  AnalyzerErrorGroup(this.errors);

  String get message => toString();

  @override
  String toString() => errors.join("\n");
}
