// 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 leg_apiimpl;

import 'dart:async';

import '../compiler.dart' as api;
import 'dart2jslib.dart' as leg;
import 'tree/tree.dart' as tree;
import 'elements/elements.dart' as elements;
import 'ssa/tracer.dart' as ssa;
import '../../libraries.dart';
import 'source_file.dart';

class Compiler extends leg.Compiler {
  api.CompilerInputProvider provider;
  api.DiagnosticHandler handler;
  final Uri libraryRoot;
  final Uri packageRoot;
  List<String> options;
  Map<String, dynamic> environment;
  bool mockableLibraryUsed = false;
  final Set<String> allowedLibraryCategories;

  Compiler(this.provider,
           api.CompilerOutputProvider outputProvider,
           this.handler,
           this.libraryRoot,
           this.packageRoot,
           List<String> options,
           this.environment)
      : this.options = options,
        this.allowedLibraryCategories = getAllowedLibraryCategories(options),
        super(
            tracer: new ssa.HTracer(
                ssa.GENERATE_SSA_TRACE ? outputProvider('dart', 'cfg') : null),
            outputProvider: outputProvider,
            enableTypeAssertions: hasOption(options, '--enable-checked-mode'),
            enableUserAssertions: hasOption(options, '--enable-checked-mode'),
            trustTypeAnnotations:
                hasOption(options, '--trust-type-annotations'),
            enableMinification: hasOption(options, '--minify'),
            enableNativeLiveTypeAnalysis:
                !hasOption(options, '--disable-native-live-type-analysis'),
            emitJavaScript: !hasOption(options, '--output-type=dart'),
            analyzeAllFlag: hasOption(options, '--analyze-all'),
            analyzeOnly: hasOption(options, '--analyze-only'),
            analyzeSignaturesOnly:
                hasOption(options, '--analyze-signatures-only'),
            strips: extractCsvOption(options, '--force-strip='),
            enableConcreteTypeInference:
                hasOption(options, '--enable-concrete-type-inference'),
            disableTypeInferenceFlag:
                hasOption(options, '--disable-type-inference'),
            preserveComments: hasOption(options, '--preserve-comments'),
            verbose: hasOption(options, '--verbose'),
            sourceMapUri: extractSourceMapUri(options),
            terseDiagnostics: hasOption(options, '--terse'),
            dumpInfo: hasOption(options, '--dump-info'),
            buildId: extractStringOption(
                options, '--build-id=',
                "build number could not be determined")) {
    if (!libraryRoot.path.endsWith("/")) {
      throw new ArgumentError("libraryRoot must end with a /");
    }
    if (packageRoot != null && !packageRoot.path.endsWith("/")) {
      throw new ArgumentError("packageRoot must end with a /");
    }
  }

  static String extractStringOption(List<String> options,
                                    String prefix,
                                    String defaultValue) {
    for (String option in options) {
      if (option.startsWith(prefix)) {
        return option.substring(prefix.length);
      }
    }
    return defaultValue;
  }

  static Uri extractSourceMapUri(List<String> options) {
    var option = extractStringOption(options, '--source-map=', null);
    return (option == null) ? null : Uri.parse(option);
  }

  // CSV: Comma separated values.
  static List<String> extractCsvOption(List<String> options, String prefix) {
    for (String option in options) {
      if (option.startsWith(prefix)) {
        return option.substring(prefix.length).split(',');
      }
    }
    return const <String>[];
  }

  static Set<String> getAllowedLibraryCategories(List<String> options) {
    var result = extractCsvOption(options, '--categories=');
    if (result.isEmpty) {
      result = ['Client'];
    }
    result.add('Shared');
    result.add('Internal');
    return new Set<String>.from(result);
  }

  static bool hasOption(List<String> options, String option) {
    return options.indexOf(option) >= 0;
  }

  // TODO(johnniwinther): Merge better with [translateDartUri] when
  // [scanBuiltinLibrary] is removed.
  String lookupLibraryPath(String dartLibraryName) {
    LibraryInfo info = LIBRARIES[dartLibraryName];
    if (info == null) return null;
    if (!info.isDart2jsLibrary) return null;
    if (!allowedLibraryCategories.contains(info.category)) return null;
    String path = info.dart2jsPath;
    if (path == null) {
      path = info.path;
    }
    return "lib/$path";
  }

  String lookupPatchPath(String dartLibraryName) {
    LibraryInfo info = LIBRARIES[dartLibraryName];
    if (info == null) return null;
    if (!info.isDart2jsLibrary) return null;
    String path = info.dart2jsPatchPath;
    if (path == null) return null;
    return "lib/$path";
  }

  Future<elements.LibraryElement> scanBuiltinLibrary(String path) {
    Uri uri = libraryRoot.resolve(lookupLibraryPath(path));
    Uri canonicalUri = new Uri(scheme: "dart", path: path);
    return libraryLoader.loadLibrary(uri, null, canonicalUri);
  }

  void log(message) {
    handler(null, null, null, message, api.Diagnostic.VERBOSE_INFO);
  }

  /// See [leg.Compiler.translateResolvedUri].
  Uri translateResolvedUri(elements.LibraryElement importingLibrary,
                           Uri resolvedUri, tree.Node node) {
    if (resolvedUri.scheme == 'dart') {
      return translateDartUri(importingLibrary, resolvedUri, node);
    }
    return resolvedUri;
  }

  /**
   * Reads the script designated by [readableUri].
   */
  Future<leg.Script> readScript(Uri readableUri,
                                [elements.Element element, tree.Node node]) {
    if (!readableUri.isAbsolute) {
      internalError('Relative uri $readableUri provided to readScript(Uri)',
                    node: node);
    }

    // TODO(johnniwinther): Add [:report(..., {Element element}):] to
    // report methods in Compiler.
    void reportReadError(exception) {
      withCurrentElement(element, () {
        reportError(node,
                    leg.MessageKind.READ_SCRIPT_ERROR,
                    {'uri': readableUri, 'exception': exception});
      });
    }

    Uri resourceUri = translateUri(readableUri, node);
    // TODO(johnniwinther): Wrap the result from [provider] in a specialized
    // [Future] to ensure that we never execute an asynchronous action without
    // setting up the current element of the compiler.
    return new Future.sync(() => callUserProvider(resourceUri)).then((data) {
      SourceFile sourceFile;
      String resourceUriString = resourceUri.toString();
      if (data is List<int>) {
        sourceFile = new Utf8BytesSourceFile(resourceUriString, data);
      } else if (data is String) {
        sourceFile = new StringSourceFile(resourceUriString, data);
      } else {
        String message = "Expected a 'String' or a 'List<int>' from the input "
                         "provider, but got: ${Error.safeToString(data)}.";
        reportReadError(message);
      }
      // We use [readableUri] as the URI for the script since need to preserve
      // the scheme in the script because [Script.uri] is used for resolving
      // relative URIs mentioned in the script. See the comment on
      // [LibraryLoader] for more details.
      return new leg.Script(readableUri, sourceFile);
    }).catchError((error) {
      reportReadError(error);
      return null;
    });
  }

  /**
   * Translates a readable URI into a resource URI.
   *
   * See [LibraryLoader] for terminology on URIs.
   */
  Uri translateUri(Uri readableUri, tree.Node node) {
    switch (readableUri.scheme) {
      case 'package': return translatePackageUri(readableUri, node);
      default: return readableUri;
    }
  }

  Uri translateDartUri(elements.LibraryElement importingLibrary,
                       Uri resolvedUri, tree.Node node) {
    LibraryInfo libraryInfo = LIBRARIES[resolvedUri.path];
    String path = lookupLibraryPath(resolvedUri.path);
    if (libraryInfo != null &&
        libraryInfo.category == "Internal") {
      bool allowInternalLibraryAccess = false;
      if (importingLibrary != null) {
        if (importingLibrary.isPlatformLibrary || importingLibrary.isPatch) {
          allowInternalLibraryAccess = true;
        } else if (importingLibrary.canonicalUri.path.contains(
                       'dart/tests/compiler/dart2js_native')) {
          allowInternalLibraryAccess = true;
        }
      }
      if (!allowInternalLibraryAccess) {
        if (importingLibrary != null) {
          reportError(
              node,
              leg.MessageKind.INTERNAL_LIBRARY_FROM,
              {'resolvedUri': resolvedUri,
               'importingUri': importingLibrary.canonicalUri});
        } else {
          reportError(
              node,
              leg.MessageKind.INTERNAL_LIBRARY,
              {'resolvedUri': resolvedUri});
        }
      }
    }
    if (path == null) {
      reportError(node, leg.MessageKind.LIBRARY_NOT_FOUND,
                  {'resolvedUri': resolvedUri});
      return null;
    }
    if (resolvedUri.path == 'html' ||
        resolvedUri.path == 'io') {
      // TODO(ahe): Get rid of mockableLibraryUsed when test.dart
      // supports this use case better.
      mockableLibraryUsed = true;
    }
    return libraryRoot.resolve(path);
  }

  Uri resolvePatchUri(String dartLibraryPath) {
    String patchPath = lookupPatchPath(dartLibraryPath);
    if (patchPath == null) return null;
    return libraryRoot.resolve(patchPath);
  }

  Uri translatePackageUri(Uri uri, tree.Node node) {
    if (packageRoot == null) {
      reportFatalError(
          node, leg.MessageKind.PACKAGE_ROOT_NOT_SET, {'uri': uri});
    }
    return packageRoot.resolve(uri.path);
  }

  Future<bool> run(Uri uri) {
    log('Allowed library categories: $allowedLibraryCategories');
    return super.run(uri).then((bool success) {
      int cumulated = 0;
      for (final task in tasks) {
        cumulated += task.timing;
        log('${task.name} took ${task.timing}msec');
      }
      int total = totalCompileTime.elapsedMilliseconds;
      log('Total compile-time ${total}msec;'
          ' unaccounted ${total - cumulated}msec');
      return success;
    });
  }

  void reportDiagnostic(leg.SourceSpan span, String message,
                        api.Diagnostic kind) {
    if (identical(kind, api.Diagnostic.ERROR)
        || identical(kind, api.Diagnostic.CRASH)) {
      compilationFailed = true;
    }
    // [:span.uri:] might be [:null:] in case of a [Script] with no [uri]. For
    // instance in the [Types] constructor in typechecker.dart.
    if (span == null || span.uri == null) {
      callUserHandler(null, null, null, message, kind);
    } else {
      callUserHandler(
          translateUri(span.uri, null), span.begin, span.end, message, kind);
    }
  }

  bool get isMockCompilation {
    return mockableLibraryUsed
      && (options.indexOf('--allow-mock-compilation') != -1);
  }

  void callUserHandler(Uri uri, int begin, int end,
                       String message, api.Diagnostic kind) {
    try {
      handler(uri, begin, end, message, kind);
    } catch (ex, s) {
      diagnoseCrashInUserCode(
          'Uncaught exception in diagnostic handler', ex, s);
      rethrow;
    }
  }

  Future callUserProvider(Uri uri) {
    try {
      return provider(uri);
    } catch (ex, s) {
      diagnoseCrashInUserCode('Uncaught exception in input provider', ex, s);
      rethrow;
    }
  }

  void diagnoseCrashInUserCode(String message, exception, stackTrace) {
    hasCrashed = true;
    print('$message: ${tryToString(exception)}');
    print(tryToString(stackTrace));
  }

  fromEnvironment(String name) => environment[name];
}
