// 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 'dart:convert';

import 'package:package_config/packages.dart';
import 'package:package_config/packages_file.dart' as pkgs;
import 'package:package_config/src/packages_impl.dart'
    show MapPackages, NonFilePackagesDirectoryPackages;
import 'package:package_config/src/util.dart' show checkValidPackageUri;

import '../compiler_new.dart' as api;
import 'common/tasks.dart' show GenericTask, Measurer;
import 'common.dart';
import 'common/backend_api.dart' show Backend;
import 'compiler.dart';
import 'diagnostics/messages.dart' show Message;
import 'elements/elements.dart' as elements;
import 'environment.dart';
import 'io/source_file.dart';
import 'options.dart' show CompilerOptions;
import 'platform_configuration.dart' as platform_configuration;
import 'resolved_uri_translator.dart';
import 'script.dart';
import 'serialization/system.dart';

/// Implements the [Compiler] using a [api.CompilerInput] for supplying the
/// sources.
class CompilerImpl extends Compiler {
  api.CompilerInput provider;
  api.CompilerDiagnostics handler;
  Packages packages;

  bool get mockableLibraryUsed => resolvedUriTranslator.isSet
      ? resolvedUriTranslator.mockableLibraryUsed
      : false;

  ForwardingResolvedUriTranslator resolvedUriTranslator;

  GenericTask userHandlerTask;
  GenericTask userProviderTask;
  GenericTask userPackagesDiscoveryTask;

  Uri get libraryRoot => options.platformConfigUri.resolve(".");

  CompilerImpl(this.provider, api.CompilerOutput outputProvider, this.handler,
      CompilerOptions options,
      {MakeBackendFuncion makeBackend, MakeReporterFunction makeReporter})
      : resolvedUriTranslator = new ForwardingResolvedUriTranslator(),
        super(
            options: options,
            outputProvider: outputProvider,
            environment: new _Environment(options.environment),
            makeBackend: makeBackend,
            makeReporter: makeReporter) {
    _Environment env = environment;
    env.compiler = this;
    tasks.addAll([
      userHandlerTask = new GenericTask('Diagnostic handler', this),
      userProviderTask = new GenericTask('Input provider', this),
      userPackagesDiscoveryTask = new GenericTask('Package discovery', this),
    ]);
  }

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

  /**
   * Reads the script designated by [readableUri].
   */
  Future<Script> readScript(Uri readableUri, [Spannable node]) {
    if (!readableUri.isAbsolute) {
      if (node == null) node = NO_LOCATION_SPANNABLE;
      reporter.internalError(
          node, 'Relative uri $readableUri provided to readScript(Uri).');
    }

    // We need to store the current element since we are reporting read errors
    // asynchronously and therefore need to restore the current element for
    // [node] to be valid.
    elements.Element element = currentElement;
    void reportReadError(exception) {
      if (element == null || node == null) {
        reporter.reportErrorMessage(
            new SourceSpan(readableUri, 0, 0),
            MessageKind.READ_SELF_ERROR,
            {'uri': readableUri, 'exception': exception});
      } else {
        reporter.withCurrentElement(element, () {
          reporter.reportErrorMessage(node, MessageKind.READ_SCRIPT_ERROR,
              {'uri': readableUri, 'exception': exception});
        });
      }
    }

    Uri resourceUri = translateUri(node, readableUri);
    if (resourceUri == null) return _synthesizeScript(readableUri);
    if (resourceUri.scheme == 'dart-ext') {
      if (!options.allowNativeExtensions) {
        reporter.withCurrentElement(element, () {
          reporter.reportErrorMessage(node, MessageKind.DART_EXT_NOT_SUPPORTED);
        });
      }
      return _synthesizeScript(readableUri);
    }

    // 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((SourceFile sourceFile) {
      // 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 Script(readableUri, resourceUri, sourceFile);
    }).catchError((error) {
      reportReadError(error);
      return _synthesizeScript(readableUri);
    });
  }

  Future<Script> _synthesizeScript(Uri readableUri) {
    return new Future.value(new Script.synthetic(readableUri));
  }

  /**
   * Translates a readable URI into a resource URI.
   *
   * See [LibraryLoader] for terminology on URIs.
   */
  Uri translateUri(Spannable node, Uri uri) =>
      uri.scheme == 'package' ? translatePackageUri(node, uri) : uri;

  Uri translatePackageUri(Spannable node, Uri uri) {
    try {
      checkValidPackageUri(uri);
    } on ArgumentError catch (e) {
      reporter.reportErrorMessage(node, MessageKind.INVALID_PACKAGE_URI,
          {'uri': uri, 'exception': e.message});
      return null;
    }
    return packages.resolve(uri, notFound: (Uri notFound) {
      reporter.reportErrorMessage(
          node, MessageKind.LIBRARY_NOT_FOUND, {'resolvedUri': uri});
      return null;
    });
  }

  Future<elements.LibraryElement> analyzeUri(Uri uri,
      {bool skipLibraryWithPartOfTag: true}) {
    Future setupFuture = new Future.value();
    if (resolvedUriTranslator.isNotSet) {
      setupFuture = setupFuture.then((_) => setupSdk());
    }
    if (packages == null) {
      setupFuture = setupFuture.then((_) => setupPackages(uri));
    }
    return setupFuture.then((_) {
      return super
          .analyzeUri(uri, skipLibraryWithPartOfTag: skipLibraryWithPartOfTag);
    });
  }

  Future setupPackages(Uri uri) {
    if (options.packageRoot != null) {
      // Use "non-file" packages because the file version requires a [Directory]
      // and we can't depend on 'dart:io' classes.
      packages = new NonFilePackagesDirectoryPackages(options.packageRoot);
    } else if (options.packageConfig != null) {
      return callUserProvider(options.packageConfig)
          .then((SourceFile sourceFile) {
        List<int> configContents = sourceFile.slowUtf8ZeroTerminatedBytes();
        // The input provider may put a trailing 0 byte when it reads a source
        // file, which confuses the package config parser.
        if (configContents.length > 0 && configContents.last == 0) {
          configContents = configContents.sublist(0, configContents.length - 1);
        }
        packages =
            new MapPackages(pkgs.parse(configContents, options.packageConfig));
      }).catchError((error) {
        reporter.reportErrorMessage(
            NO_LOCATION_SPANNABLE,
            MessageKind.INVALID_PACKAGE_CONFIG,
            {'uri': options.packageConfig, 'exception': error});
        packages = Packages.noPackages;
      });
    } else {
      if (options.packagesDiscoveryProvider == null) {
        packages = Packages.noPackages;
      } else {
        return callUserPackagesDiscovery(uri).then((p) {
          packages = p;
        });
      }
    }
    return new Future.value();
  }

  Future<Null> setupSdk() {
    Future future = new Future.value(null);
    if (options.resolutionInput != null) {
      reporter.log('Reading serialized data from ${options.resolutionInput}');
      future = callUserProvider(options.resolutionInput)
          .then((SourceFile sourceFile) {
        serialization.deserializeFromText(sourceFile.slowText());
      });
    }
    if (resolvedUriTranslator.isNotSet) {
      future = future.then((_) {
        return platform_configuration
            .load(options.platformConfigUri, provider)
            .then((Map<String, Uri> mapping) {
          resolvedUriTranslator.resolvedUriTranslator =
              new ResolvedUriTranslator(mapping, reporter);
        });
      });
    }
    // The incremental compiler sets up the sdk before run.
    // Therefore this will be called a second time.
    return future;
  }

  Future<bool> run(Uri uri) {
    Duration setupDuration = measurer.wallClock.elapsed;
    return selfTask.measureSubtask("CompilerImpl.run", () {
      log('Using platform configuration at ${options.platformConfigUri}');

      return setupSdk().then((_) => setupPackages(uri)).then((_) {
        assert(resolvedUriTranslator.isSet);
        assert(packages != null);

        return super.run(uri);
      }).then((bool success) {
        if (options.verbose) {
          StringBuffer timings = new StringBuffer();
          computeTimings(setupDuration, timings);
          log("$timings");
        }
        return success;
      });
    });
  }

  void computeTimings(Duration setupDuration, StringBuffer timings) {
    timings.writeln("Timings:");
    Duration totalDuration = measurer.wallClock.elapsed;
    Duration asyncDuration = measurer.asyncWallClock.elapsed;
    Duration cumulatedDuration = Duration.ZERO;
    for (final task in tasks) {
      String running = task.isRunning ? "*" : "";
      Duration duration = task.duration;
      if (duration != Duration.ZERO) {
        cumulatedDuration += duration;
        timings.writeln('    $running${task.name} took'
            ' ${duration.inMilliseconds}msec');
        for (String subtask in task.subtasks) {
          int subtime = task.getSubtaskTime(subtask);
          String running = task.getSubtaskIsRunning(subtask) ? "*" : "";
          timings.writeln(
              '    $running${task.name} > $subtask took ${subtime}msec');
        }
      }
    }
    Duration unaccountedDuration =
        totalDuration - cumulatedDuration - setupDuration - asyncDuration;
    double percent =
        unaccountedDuration.inMilliseconds * 100 / totalDuration.inMilliseconds;
    timings.write('    Total compile-time ${totalDuration.inMilliseconds}msec;'
        ' setup ${setupDuration.inMilliseconds}msec;'
        ' async ${asyncDuration.inMilliseconds}msec;'
        ' unaccounted ${unaccountedDuration.inMilliseconds}msec'
        ' (${percent.toStringAsFixed(2)}%)');
  }

  void reportDiagnostic(DiagnosticMessage message,
      List<DiagnosticMessage> infos, api.Diagnostic kind) {
    _reportDiagnosticMessage(message, kind);
    for (DiagnosticMessage info in infos) {
      _reportDiagnosticMessage(info, api.Diagnostic.INFO);
    }
  }

  void _reportDiagnosticMessage(
      DiagnosticMessage diagnosticMessage, api.Diagnostic kind) {
    // [:span.uri:] might be [:null:] in case of a [Script] with no [uri]. For
    // instance in the [Types] constructor in typechecker.dart.
    SourceSpan span = diagnosticMessage.sourceSpan;
    Message message = diagnosticMessage.message;
    if (span == null || span.uri == null) {
      callUserHandler(message, null, null, null, '$message', kind);
    } else {
      callUserHandler(
          message, span.uri, span.begin, span.end, '$message', kind);
    }
  }

  bool get isMockCompilation =>
      mockableLibraryUsed && options.allowMockCompilation;

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

  Future<SourceFile> callUserProvider(Uri uri) {
    try {
      return userProviderTask
          .measureIo(() => provider.readFromUri(uri))
          .then((data) {
        SourceFile sourceFile;
        if (data is List<int>) {
          sourceFile = new Utf8BytesSourceFile(uri, data);
        } else if (data is String) {
          sourceFile = new StringSourceFile.fromUri(uri, data);
        } else {
          throw "Expected a 'String' or a 'List<int>' from the input "
              "provider, but got: ${Error.safeToString(data)}.";
        }
        return sourceFile;
      });
    } catch (ex, s) {
      reportCrashInUserCode('Uncaught exception in input provider', ex, s);
      rethrow;
    }
  }

  Future<Packages> callUserPackagesDiscovery(Uri uri) {
    try {
      return userPackagesDiscoveryTask
          .measureIo(() => options.packagesDiscoveryProvider(uri));
    } catch (ex, s) {
      reportCrashInUserCode('Uncaught exception in package discovery', ex, s);
      rethrow;
    }
  }

  Uri resolvePatchUri(String libraryName) {
    return backend.resolvePatchUri(libraryName, options.platformConfigUri);
  }
}

class _Environment implements Environment {
  final Map<String, String> definitions;

  // TODO(sigmund): break the circularity here: Compiler needs an environment to
  // initialize the library loader, but the environment here needs to know about
  // how the sdk is set up and about whether the backend supports mirrors.
  CompilerImpl compiler;

  _Environment(this.definitions);

  String valueOf(String name) {
    assert(invariant(
        NO_LOCATION_SPANNABLE, compiler.resolvedUriTranslator != null,
        message: "setupSdk() has not been run"));

    var result = definitions[name];
    if (result != null || definitions.containsKey(name)) return result;
    if (!name.startsWith(_dartLibraryEnvironmentPrefix)) return null;

    String libraryName = name.substring(_dartLibraryEnvironmentPrefix.length);

    // Private libraries are not exposed to the users.
    if (libraryName.startsWith("_")) return null;

    if (compiler.resolvedUriTranslator.sdkLibraries.containsKey(libraryName)) {
      // Dart2js always "supports" importing 'dart:mirrors' but will abort
      // the compilation at a later point if the backend doesn't support
      // mirrors. In this case 'mirrors' should not be in the environment.
      if (libraryName == 'mirrors') {
        return compiler.backend.supportsReflection ? "true" : null;
      }
      return "true";
    }
    return null;
  }
}

/// For every 'dart:' library, a corresponding environment variable is set
/// to "true". The environment variable's name is the concatenation of
/// this prefix and the name (without the 'dart:'.
///
/// For example 'dart:html' has the environment variable 'dart.library.html' set
/// to "true".
const String _dartLibraryEnvironmentPrefix = 'dart.library.';
