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

library compiler;

import 'dart:async';
import 'package:package_config/packages.dart';
import 'compiler_new.dart' as new_api;
import 'src/old_to_new_api.dart';

// Unless explicitly allowed, passing [:null:] for any argument to the
// methods of library will result in an Error being thrown.

/**
 * Returns a future that completes to the source corresponding to [uri].
 * If an exception occurs, the future completes with this exception.
 *
 * The source can be represented either as a [:List<int>:] of UTF-8 bytes or as
 * a [String].
 *
 * The following text is non-normative:
 *
 * It is recommended to return a UTF-8 encoded list of bytes because the scanner
 * is more efficient in this case. In either case, the data structure is
 * expected to hold a zero element at the last position. If this is not the
 * case, the entire data structure is copied before scanning.
 */
typedef Future/*<String | List<int>>*/ CompilerInputProvider(Uri uri);

/// Deprecated, please use [CompilerInputProvider] instead.
typedef Future<String> ReadStringFromUri(Uri uri);

/**
 * Returns an [EventSink] that will serve as compiler output for the given
 * component.
 *
 * Components are identified by [name] and [extension]. By convention,
 * the empty string [:"":] will represent the main script
 * (corresponding to the script parameter of [compile]) even if the
 * main script is a library. For libraries that are compiled
 * separately, the library name is used.
 *
 * At least the following extensions can be expected:
 *
 * * "js" for JavaScript output.
 * * "js.map" for source maps.
 * * "dart" for Dart output.
 * * "dart.map" for source maps.
 *
 * As more features are added to the compiler, new names and
 * extensions may be introduced.
 */
typedef EventSink<String> CompilerOutputProvider(String name,
                                                 String extension);

/**
 * Invoked by the compiler to report diagnostics. If [uri] is
 * [:null:], so are [begin] and [end]. No other arguments may be
 * [:null:]. If [uri] is not [:null:], neither are [begin] and
 * [end]. [uri] indicates the compilation unit from where the
 * diagnostic originates. [begin] and [end] are zero-based character
 * offsets from the beginning of the compilation unit. [message] is the
 * diagnostic message, and [kind] indicates indicates what kind of
 * diagnostic it is.
 */
typedef void DiagnosticHandler(Uri uri, int begin, int end,
                               String message, Diagnostic kind);

/**
 * Provides a package lookup mechanism in the case that no package root or
 * package resolution configuration file are explicitly specified.
 */
typedef Future<Packages> PackagesDiscoveryProvider(Uri uri);

/// Information resulting from the compilation.
class CompilationResult {
  /// `true` if the compilation succeeded, that is, compilation didn't fail due
  /// to compile-time errors and/or internal errors.
  final bool isSuccess;

  /// The compiler object used for the compilation.
  ///
  /// Note: The type of [compiler] is implementation dependent and may vary.
  /// Use only for debugging and testing.
  final compiler;

  CompilationResult(this.compiler, {this.isSuccess: true});
}

/**
 * Returns a future that completes to a non-null String when [script]
 * has been successfully compiled.
 *
 * The compiler output is obtained by providing an [outputProvider].
 *
 * If the compilation fails, the future's value will be [:null:] and
 * [handler] will have been invoked at least once with [:kind ==
 * Diagnostic.ERROR:] or [:kind == Diagnostic.CRASH:].
 *
 * Deprecated: if no [outputProvider] is given, the future completes
 * to the compiled script. This behavior will be removed in the future
 * as the compiler may create multiple files to support lazy loading
 * of libraries.
 */
Future<CompilationResult> compile(
    Uri script,
    Uri libraryRoot,
    Uri packageRoot,
    CompilerInputProvider inputProvider,
    DiagnosticHandler handler,
    [List<String> options = const [],
     CompilerOutputProvider outputProvider,
     Map<String, dynamic> environment = const {},
     Uri packageConfig,
     PackagesDiscoveryProvider packagesDiscoveryProvider]) {

  new_api.CompilerOptions compilerOptions = new new_api.CompilerOptions(
      entryPoint: script,
      libraryRoot: libraryRoot,
      packageRoot: packageRoot,
      packageConfig: packageConfig,
      packagesDiscoveryProvider: packagesDiscoveryProvider,
      options: options,
      environment: environment);

  new_api.CompilerInput compilerInput = new LegacyCompilerInput(inputProvider);
  new_api.CompilerDiagnostics compilerDiagnostics =
      new LegacyCompilerDiagnostics(handler);
  new_api.CompilerOutput compilerOutput =
      new LegacyCompilerOutput(outputProvider);

  return new_api.compile(compilerOptions, compilerInput,
                         compilerDiagnostics, compilerOutput)
      .then((new_api.CompilationResult result) {
    return new CompilationResult(result.compiler, isSuccess: result.isSuccess);
  });
}

/**
 * Kind of diagnostics that the compiler can report.
 */
class Diagnostic {
  /**
   * An error as identified by the "Dart Programming Language
   * Specification" [http://www.dartlang.org/docs/spec/].
   *
   * Note: the compiler may still produce an executable result after
   * reporting a compilation error. The specification says:
   *
   * "A compile-time error must be reported by a Dart compiler before
   * the erroneous code is executed." and "If a compile-time error
   * occurs within the code of a running isolate A, A is immediately
   * suspended."
   *
   * This means that the compiler can generate code that when executed
   * terminates execution.
   */
  static const Diagnostic ERROR = const Diagnostic(1, 'error');

  /**
   * A warning as identified by the "Dart Programming Language
   * Specification" [http://www.dartlang.org/docs/spec/].
   */
  static const Diagnostic WARNING = const Diagnostic(2, 'warning');

  /**
   * Any other warning that is not covered by [WARNING].
   */
  static const Diagnostic HINT = const Diagnostic(4, 'hint');

  /**
   * Additional information about the preceding non-info diagnostic from the
   * compiler.
   *
   * For example, consider a duplicated definition. The compiler first emits a
   * message about the duplicated definition, then emits an info message about
   * the location of the existing definition.
   */
  static const Diagnostic INFO = const Diagnostic(8, 'info');

  /**
   * Informational messages that shouldn't be printed unless
   * explicitly requested by the user of a compiler.
   */
  static const Diagnostic VERBOSE_INFO = const Diagnostic(16, 'verbose info');

  /**
   * An internal error in the compiler.
   */
  static const Diagnostic CRASH = const Diagnostic(32, 'crash');

  /**
   * An [int] representation of this kind. The ordinals are designed
   * to be used as bitsets.
   */
  final int ordinal;

  /**
   * The name of this kind.
   */
  final String name;

  /**
   * This constructor is not private to support user-defined
   * diagnostic kinds.
   */
  const Diagnostic(this.ordinal, this.name);

  String toString() => name;
}
