// 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_new.dart' as api;
import 'package:compiler/src/common/names.dart' show Uris;
import 'package:compiler/src/constants/expressions.dart';
import 'package:compiler/src/elements/resolution_types.dart'
    show ResolutionDartType;
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/library_loader.dart' show LoadedLibraries;
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 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 OutputUnit;

import 'package:compiler/src/resolution/deferred_load.dart'
    show AstDeferredLoadTask;

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.CompilerDiagnostics diagnosticHandler;
  final api.CompilerInput provider = null;

  /// 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 LibrarySourceProvider librariesOverride;
  final DiagnosticCollector diagnosticCollector = new DiagnosticCollector();
  final ResolvedUriTranslator resolvedUriTranslator =
      new MockResolvedUriTranslator();
  final Measurer measurer = new Measurer();
  LibraryElement mainApp;

  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.CompilerOutput outputProvider,
      LibrarySourceProvider this.librariesOverride})
      : sourceFiles = new Map<String, SourceFile>(),
        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: outputProvider) {
    deferredLoadTask = new MockDeferredLoadTask(this);

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

    registerSource(
        Uris.dart__js_helper, buildLibrarySource(DEFAULT_JS_HELPER_LIBRARY));
    registerSource(Uris.dart__foreign_helper,
        buildLibrarySource(DEFAULT_FOREIGN_HELPER_LIBRARY));
    registerSource(Uris.dart__interceptors,
        buildLibrarySource(DEFAULT_INTERCEPTORS_LIBRARY));
    registerSource(Uris.dart__isolate_helper,
        buildLibrarySource(DEFAULT_ISOLATE_HELPER_LIBRARY));
    registerSource(Uris.dart_mirrors, DEFAULT_MIRRORS_SOURCE);
    registerSource(Uris.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));
  }

  /// 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((LoadedLibraries loadedLibraries) {
      processLoadedLibraries(loadedLibraries);
      mainApp = loadedLibraries.rootLibrary;
      startResolution();
      // 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.
      ClassElement objectClass = resolution.commonElements.objectClass;
      objectClass.ensureResolved(resolution);
    }).then((_) => uri);
  }

  Future<bool> 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.report(message.message, uri, begin, end, text, kind);
      }
    }

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

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

  TreeElementMapping resolveNodeStatement(
      Node tree, ExecutableElement element) {
    ResolverVisitor visitor = new ResolverVisitor(
        this.resolution,
        element,
        new ResolutionRegistry(
            this.backend.target, 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() {
    LibraryElement library = mainApp;
    Element mockElement = new MockElement(library.entryCompilationUnit);
    ResolverVisitor visitor = new ResolverVisitor(
        this.resolution,
        mockElement,
        new ResolutionRegistry(
            this.backend.target, 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<T> create<T>(T f(MockCompiler compiler)) {
    MockCompiler compiler = new MockCompiler.internal();
    return compiler.init().then((_) => f(compiler));
  }
}

class MockResolvedUriTranslator implements ResolvedUriTranslator {
  static final dynamic _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<ResolutionDartType> get typeVariables => <ResolutionDartType>[];
  MockTypeVariablesScope(Scope parent) : super(parent);
  String toString() => 'MockTypeVariablesScope($parent)';
}

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

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

api.CompilerDiagnostics createHandler(MockCompiler compiler, String text,
    {bool verbose: false}) {
  return new LegacyCompilerDiagnostics(
      (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.CompilerOutput 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;
}
