// 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.
library pub.dart;

import 'dart:async' hide TimeoutException;
import 'dart:isolate';

import 'package:analyzer/analyzer.dart';
import 'package:path/path.dart' as path;
import 'package:stack_trace/stack_trace.dart';
import '../../../compiler/compiler.dart' as compiler;
import '../../../compiler/implementation/source_file_provider.dart'
    show FormattingDiagnosticHandler, CompilerSourceFileProvider;
import '../../../compiler/implementation/filenames.dart'
    show appendSlash;

import 'io.dart';
import 'sdk.dart' as sdk;
import 'utils.dart';

/// Returns [entrypoint] compiled to JavaScript (or to Dart if [toDart] is
/// true).
///
/// By default, the package root is assumed to be adjacent to [entrypoint], but
/// if [packageRoot] is passed that will be used instead.
///
/// If [inputProvider] and [diagnosticHandler] are omitted, uses a default
/// [compiler.CompilerInputProvider] that loads directly from the filesystem.
/// If either is provided, both must be.
Future<String> compile(String entrypoint, {
    String packageRoot,
    bool toDart: false,
    bool minify: true,
    compiler.CompilerInputProvider inputProvider,
    compiler.DiagnosticHandler diagnosticHandler}) {
  return new Future.sync(() {
    var options = <String>['--categories=Client,Server'];
    if (toDart) options.add('--output-type=dart');
    if (minify) options.add('--minify');

    if (packageRoot == null) {
      packageRoot = path.join(path.dirname(entrypoint), 'packages');
    }

    // Must either pass both of these or neither.
    if ((inputProvider == null) != (diagnosticHandler == null)) {
      throw new ArgumentError("If either inputProvider or diagnosticHandler "
          "is passed, then both must be.");
    }

    if (inputProvider == null) {
      var provider = new CompilerSourceFileProvider();
      inputProvider = provider.readStringFromUri;
      diagnosticHandler = new FormattingDiagnosticHandler(provider)
          .diagnosticHandler;
    }

    return compiler.compile(
        path.toUri(entrypoint),
        path.toUri(appendSlash(_libPath)),
        path.toUri(appendSlash(packageRoot)),
        inputProvider, diagnosticHandler, options).then((js) {
      if (js == null) throw new CompilerException(entrypoint);
      return js;
    });
  });
}

/// Returns the path to the directory containing the Dart core libraries.
///
/// This corresponds to the "sdk" directory in the repo and to the root of the
/// compiled SDK.
String get _libPath {
  if (runningFromSdk) return sdk.rootDirectory;
  return path.join(repoRoot, 'sdk');
}

/// Returns whether [dart] looks like an entrypoint file.
bool isEntrypoint(CompilationUnit dart) {
  // 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.isEmpty;
  });
}

/// Runs [code] in an isolate.
///
/// [code] should be the contents of a Dart entrypoint. It may contain imports;
/// they will be resolved in the same context as the host isolate. [message] is
/// passed to the [main] method of the code being run; the caller is responsible
/// for using this to establish communication with the isolate.
///
/// Returns a Future that will fire when the isolate has been spawned. If the
/// isolate fails to spawn, the Future will complete with an error.
Future runInIsolate(String code, message) {
  return withTempDir((dir) {
    var dartPath = path.join(dir, 'runInIsolate.dart');
    writeTextFile(dartPath, code, dontLogContents: true);
    var port = new ReceivePort();
    return Isolate.spawn(_isolateBuffer, {
      'replyTo': port.sendPort,
      'uri': path.toUri(dartPath).toString(),
      'message': message
    }).then((_) => port.first).then((response) {
      if (response['type'] == 'success') return null;
      assert(response['type'] == 'error');
      return new Future.error(
          new CrossIsolateException.deserialize(response['error']));
    });
  });
}

// TODO(nweiz): remove this when issue 12617 is fixed.
/// A function used as a buffer between the host isolate and [spawnUri].
///
/// [spawnUri] synchronously loads the file and its imports, which can deadlock
/// the host isolate if there's an HTTP import pointing at a server in the host.
/// Adding an additional isolate in the middle works around this.
void _isolateBuffer(message) {
  var replyTo = message['replyTo'];
  // TODO(floitsch): If we do it right we shouldn't need to capture synchronous
  // errors.
  new Future.sync(() {
    return Isolate.spawnUri(Uri.parse(message['uri']), [], message['message']);
  }).then((_) => replyTo.send({'type': 'success'})).catchError((e, stack) {
    replyTo.send({
      'type': 'error',
      'error': CrossIsolateException.serialize(e, stack)
    });
  });
}

/// An exception that was originally raised in another isolate.
///
/// Exception objects can't cross isolate boundaries in general, so this class
/// wraps as much information as can be consistently serialized.
class CrossIsolateException implements Exception {
  /// The name of the type of exception thrown.
  ///
  /// This is the return value of [error.runtimeType.toString()]. Keep in mind
  /// that objects in different libraries may have the same type name.
  final String type;

  /// The exception's message, or its [toString] if it didn't expose a `message`
  /// property.
  final String message;

  /// The exception's stack trace, or `null` if no stack trace was available.
  final Trace stackTrace;

  /// Loads a [CrossIsolateException] from a serialized representation.
  ///
  /// [error] should be the result of [CrossIsolateException.serialize].
  factory CrossIsolateException.deserialize(Map error) {
    var type = error['type'];
    var message = error['message'];
    var stackTrace = error['stack'] == null ? null :
            new Trace.parse(error['stack']);
    return new CrossIsolateException._(type, message, stackTrace);
  }

  /// Loads a [CrossIsolateException] from a serialized representation.
  ///
  /// [error] should be the result of [CrossIsolateException.serialize].
  CrossIsolateException._(this.type, this.message, this.stackTrace);

  /// Serializes [error] to an object that can safely be passed across isolate
  /// boundaries.
  static Map serialize(error, [StackTrace stack]) {
    if (stack == null && error is Error) stack = error.stackTrace;
    return {
      'type': error.runtimeType.toString(),
      'message': getErrorMessage(error),
      'stack': stack == null ? null : stack.toString()
    };
  }

  String toString() => "$message\n$stackTrace";
}

/// An exception thrown when dart2js generates compiler errors.
class CompilerException extends ApplicationException {
  CompilerException(String entrypoint)
      : super('Failed to compile "$entrypoint".');
}
