// Copyright (c) 2016, 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 mock_compiler;

import 'dart:async';
import 'dart:collection';

import 'package:compiler/compiler.dart' as api;
import 'package:compiler/src/common/names.dart' show
    Uris;
import 'package:compiler/src/constants/expressions.dart';
import 'package:compiler/src/dart_types.dart' show DartType;
import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
import 'package:compiler/src/diagnostics/source_span.dart';
import 'package:compiler/src/diagnostics/spannable.dart';
import 'package:compiler/src/elements/elements.dart';
import 'package:compiler/src/elements/visitor.dart';
import 'package:compiler/src/js_backend/backend_helpers.dart' show
    BackendHelpers;
import 'package:compiler/src/js_backend/lookup_map_analysis.dart' show
    LookupMapAnalysis;
import 'package:compiler/src/io/source_file.dart';
import 'package:compiler/src/options.dart' show
    CompilerOptions;
import 'package:compiler/src/resolution/members.dart';
import 'package:compiler/src/resolution/registry.dart';
import 'package:compiler/src/resolution/scope.dart';
import 'package:compiler/src/resolution/tree_elements.dart';
import 'package:compiler/src/resolved_uri_translator.dart';
import 'package:compiler/src/script.dart';
import 'package:compiler/src/tree/tree.dart';
import 'package:compiler/src/old_to_new_api.dart';
import 'parser_helper.dart';

import 'package:compiler/src/elements/modelx.dart' show
    ElementX,
    LibraryElementX,
    ErroneousElementX,
    FunctionElementX;

import 'package:compiler/src/compiler.dart';
import 'package:compiler/src/common/tasks.dart' show Measurer;

import 'package:compiler/src/deferred_load.dart' show
    DeferredLoadTask,
    OutputUnit;

import 'mock_libraries.dart';
import 'diagnostic_helper.dart';

export 'diagnostic_helper.dart';

final Uri PATCH_CORE = new Uri(scheme: 'patch', path: 'core');

typedef String LibrarySourceProvider(Uri uri);

class MockCompiler extends Compiler {
  api.DiagnosticHandler diagnosticHandler;
  /// Expected number of warnings. If `null`, the number of warnings is
  /// not checked.
  final int expectedWarnings;
  /// Expected number of errors. If `null`, the number of errors is not checked.
  final int expectedErrors;
  final Map<String, SourceFile> sourceFiles;
  Node parsedTree;
  final String testedPatchVersion;
  final LibrarySourceProvider librariesOverride;
  final DiagnosticCollector diagnosticCollector = new DiagnosticCollector();
  final ResolvedUriTranslator resolvedUriTranslator =
      new MockResolvedUriTranslator();
  final Measurer measurer = new Measurer();

  MockCompiler.internal(
      {Map<String, String> coreSource,
       bool enableTypeAssertions: false,
       bool enableUserAssertions: false,
       bool enableMinification: false,
       bool disableTypeInference: false,
       bool analyzeAll: false,
       bool analyzeOnly: false,
       bool preserveComments: false,
       // Our unit tests check code generation output that is
       // affected by inlining support.
       bool disableInlining: true,
       bool trustTypeAnnotations: false,
       bool trustJSInteropTypeAnnotations: false,
       bool enableAsyncAwait: false,
       int this.expectedWarnings,
       int this.expectedErrors,
       api.CompilerOutputProvider outputProvider,
       String patchVersion,
       LibrarySourceProvider this.librariesOverride})
      : sourceFiles = new Map<String, SourceFile>(),
        testedPatchVersion = patchVersion,
        super(options: new CompilerOptions(
              entryPoint: new Uri(scheme: 'mock'),
              libraryRoot: Uri.parse('placeholder_library_root_for_mock/'),
              enableTypeAssertions: enableTypeAssertions,
              enableUserAssertions: enableUserAssertions,
              disableInlining: disableInlining,
              enableAssertMessage: true,
              enableMinification: enableMinification,
              disableTypeInference: disableTypeInference,
              analyzeAll: analyzeAll,
              analyzeOnly: analyzeOnly,
              preserveComments: preserveComments,
              trustTypeAnnotations: trustTypeAnnotations,
              trustJSInteropTypeAnnotations: trustJSInteropTypeAnnotations,
              shownPackageWarnings: const []),
              outputProvider: new LegacyCompilerOutput(outputProvider)) {

    deferredLoadTask = new MockDeferredLoadTask(this);

    registerSource(Uris.dart_core,
                   buildLibrarySource(DEFAULT_CORE_LIBRARY, coreSource));
    registerSource(PATCH_CORE, DEFAULT_PATCH_CORE_SOURCE);

    registerSource(BackendHelpers.DART_JS_HELPER,
                   buildLibrarySource(DEFAULT_JS_HELPER_LIBRARY));
    registerSource(BackendHelpers.DART_FOREIGN_HELPER,
                   buildLibrarySource(DEFAULT_FOREIGN_HELPER_LIBRARY));
    registerSource(BackendHelpers.DART_INTERCEPTORS,
                   buildLibrarySource(DEFAULT_INTERCEPTORS_LIBRARY));
    registerSource(BackendHelpers.DART_ISOLATE_HELPER,
                   buildLibrarySource(DEFAULT_ISOLATE_HELPER_LIBRARY));
    registerSource(Uris.dart_mirrors, DEFAULT_MIRRORS_SOURCE);
    registerSource(BackendHelpers.DART_JS_MIRRORS,
        DEFAULT_JS_MIRRORS_SOURCE);

    Map<String, String> asyncLibrarySource = <String, String>{};
    asyncLibrarySource.addAll(DEFAULT_ASYNC_LIBRARY);
    if (enableAsyncAwait) {
      asyncLibrarySource.addAll(ASYNC_AWAIT_LIBRARY);
    }
    registerSource(Uris.dart_async,
                   buildLibrarySource(asyncLibrarySource));
    registerSource(LookupMapAnalysis.PACKAGE_LOOKUP_MAP,
                   buildLibrarySource(DEFAULT_LOOKUP_MAP_LIBRARY));
  }

  String get patchVersion {
    return testedPatchVersion != null ? testedPatchVersion : super.patchVersion;
  }

  /// Initialize the mock compiler with an empty main library.
  Future<Uri> init([String mainSource = ""]) {
    Uri uri = new Uri(scheme: "mock");
    registerSource(uri, mainSource);
    return libraryLoader.loadLibrary(uri)
        .then((LibraryElement library) {
      mainApp = library;
      // We need to make sure the Object class is resolved. When registering a
      // dynamic invocation the ArgumentTypesRegistry eventually iterates over
      // the interfaces of the Object class which would be 'null' if the class
      // wasn't resolved.
      coreClasses.objectClass.ensureResolved(resolution);
    }).then((_) => uri);
  }

  Future run(Uri uri, [String mainSource = ""]) {
    return init(mainSource).then((Uri mainUri) {
      return super.run(uri == null ? mainUri : uri);
    }).then((result) {
      if (expectedErrors != null &&
          expectedErrors != diagnosticCollector.errors.length) {
        throw "unexpected error during compilation "
              "${diagnosticCollector.errors}";
      } else if (expectedWarnings != null &&
                 expectedWarnings != diagnosticCollector.warnings.length) {
        throw "unexpected warnings during compilation "
              "${diagnosticCollector.warnings}";
      } else {
        return result;
      }
    });
  }

  /**
   * Registers the [source] with [uri] making it possible load [source] as a
   * library.  If an override has been provided in [librariesOverride], that
   * is used instead.
   */
  void registerSource(Uri uri, String source) {
    if (librariesOverride != null) {
      String override = librariesOverride(uri);
      if (override != null) {
        source = override;
      }
    }
    sourceFiles[uri.toString()] = new MockFile(source);
  }

  void reportDiagnostic(DiagnosticMessage message,
                        List<DiagnosticMessage> infoMessages,
                        api.Diagnostic kind) {

    void processMessage(DiagnosticMessage message, api.Diagnostic kind) {
      SourceSpan span = message.sourceSpan;
      Uri uri;
      int begin;
      int end;
      String text = '${message.message}';
      if (span != null) {
        uri = span.uri;
        begin = span.begin;
        end = span.end;
      }
      diagnosticCollector.report(message.message, uri, begin, end, text, kind);
      if (diagnosticHandler != null) {
        diagnosticHandler(uri, begin, end, text, kind);
      }
    }

    processMessage(message, kind);
    infoMessages.forEach((i) => processMessage(i, api.Diagnostic.INFO));
  }

  CollectingTreeElements resolveStatement(String text) {
    parsedTree = parseStatement(text);
    return resolveNodeStatement(parsedTree, new MockElement(mainApp));
  }

  TreeElementMapping resolveNodeStatement(Node tree,
                                          ExecutableElement element) {
    ResolverVisitor visitor =
        new ResolverVisitor(
            this.resolution,
            element,
            new ResolutionRegistry(this.backend,
                new CollectingTreeElements(element)),
            scope: new MockTypeVariablesScope(
                element.enclosingElement.buildScope()));
    if (visitor.scope is LibraryScope ||
        visitor.scope is MockTypeVariablesScope) {
      visitor.scope = new MethodScope(visitor.scope, element);
    }
    visitor.visit(tree);
    visitor.scope = new LibraryScope(element.library);
    return visitor.registry.mapping;
  }

  resolverVisitor() {
    Element mockElement = new MockElement(mainApp.entryCompilationUnit);
    ResolverVisitor visitor =
        new ResolverVisitor(
            this.resolution,
            mockElement,
            new ResolutionRegistry(
                this.backend, new CollectingTreeElements(mockElement)),
            scope: mockElement.enclosingElement.buildScope());
    visitor.scope = new MethodScope(visitor.scope, mockElement);
    return visitor;
  }

  parseScript(String text, [LibraryElement library]) {
    if (library == null) library = mainApp;
    parseUnit(text, this, library, registerSource);
  }

  Future scanBuiltinLibraries() {
    // Do nothing. The mock core library is already handled in the constructor.
    return new Future.value();
  }

  Future<LibraryElement> scanBuiltinLibrary(String name) {
    // Do nothing. The mock core library is already handled in the constructor.
    return new Future.value();
  }

  // The mock library doesn't need any patches.
  Uri resolvePatchUri(String dartLibraryName) {
    if (dartLibraryName == 'core') {
      return PATCH_CORE;
    }
    return null;
  }

  Future<Script> readScript(Uri uri, [Spannable spannable]) {
    SourceFile sourceFile = sourceFiles[uri.toString()];
    if (sourceFile == null) throw new ArgumentError(uri);
    return new Future.value(new Script(uri, uri, sourceFile));
  }

  Element lookupElementIn(ScopeContainerElement container, name) {
    Element element = container.localLookup(name);
    return element != null
        ? element
        : new ErroneousElementX(null, null, name, container);
  }

  /// Create a new [MockCompiler] and apply it asynchronously to [f].
  static Future create(f(MockCompiler compiler)) {
    MockCompiler compiler = new MockCompiler.internal();
    return compiler.init().then((_) => f(compiler));
  }
}

class MockResolvedUriTranslator implements ResolvedUriTranslator {
  static final _emptySet = new Set();

  Uri translate(LibraryElement importingLibrary, Uri resolvedUri,
          [Spannable spannable]) =>
      resolvedUri;
  Set<Uri> get disallowedLibraryUris => _emptySet;
  bool get mockableLibraryUsed => false;
  Map<String, Uri> get sdkLibraries => const <String, Uri>{};
}

class CollectingTreeElements extends TreeElementMapping {
  final Map<Node, Element> map = new LinkedHashMap<Node, Element>();

  CollectingTreeElements(Element currentElement) : super(currentElement);

  operator []=(Node node, Element element) {
    map[node] = element;
  }

  operator [](Node node) => map[node];

  void remove(Node node) {
    map.remove(node);
  }

  List<ConstantExpression> get constants {
    List<ConstantExpression> list = <ConstantExpression>[];
    forEachConstantNode((_, c) => list.add(c));
    return list;
  }
}

class MockTypeVariablesScope extends TypeVariablesScope {
  @override
  List<DartType> get typeVariables => <DartType>[];
  MockTypeVariablesScope(Scope parent) : super(parent);
  String toString() => 'MockTypeVariablesScope($parent)';
}

// The mock compiler does not split the program in output units.
class MockDeferredLoadTask extends DeferredLoadTask {
  MockDeferredLoadTask(Compiler compiler) : super(compiler);

  OutputUnit getElementOutputUnit(dynamic dependency) {
    return mainOutputUnit;
  }
}

api.DiagnosticHandler createHandler(MockCompiler compiler, String text,
                                    {bool verbose: false}) {
  return (uri, int begin, int end, String message, kind) {
    if (kind == api.Diagnostic.VERBOSE_INFO && !verbose) return;
    SourceFile sourceFile;
    if (uri == null) {
      sourceFile = new StringSourceFile.fromName('analysis', text);
    } else {
      sourceFile = compiler.sourceFiles[uri.toString()];
    }
    if (sourceFile != null && begin != null && end != null) {
      print('${kind}: ${sourceFile.getLocationMessage(message, begin, end)}');
    } else {
      print('${kind}: $message');
    }
  };
}

class MockElement extends FunctionElementX {
  MockElement(Element enclosingElement)
      : super('', ElementKind.FUNCTION, Modifiers.EMPTY,
              enclosingElement);

  get node => null;

  parseNode(_) => null;

  bool get hasNode => false;

  accept(ElementVisitor visitor, arg) {
    return visitor.visitMethodElement(this, arg);
  }
}

// TODO(herhut): Disallow warnings and errors during compilation by default.
MockCompiler compilerFor(String code, Uri uri,
                         {bool analyzeAll: false,
                          bool analyzeOnly: false,
                          Map<String, String> coreSource,
                          bool disableInlining: true,
                          bool minify: false,
                          bool trustTypeAnnotations: false,
                          bool enableTypeAssertions: false,
                          bool enableUserAssertions: false,
                          int expectedErrors,
                          int expectedWarnings,
                          api.CompilerOutputProvider outputProvider}) {
  MockCompiler compiler = new MockCompiler.internal(
      analyzeAll: analyzeAll,
      analyzeOnly: analyzeOnly,
      coreSource: coreSource,
      disableInlining: disableInlining,
      enableMinification: minify,
      trustTypeAnnotations: trustTypeAnnotations,
      enableTypeAssertions: enableTypeAssertions,
      enableUserAssertions: enableUserAssertions,
      expectedErrors: expectedErrors,
      expectedWarnings: expectedWarnings,
      outputProvider: outputProvider);
  compiler.registerSource(uri, code);
  compiler.diagnosticHandler = createHandler(compiler, code);
  return compiler;
}
