// 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/'),
                useKernel: false,
                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>(FutureOr<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 mockCompilerFor(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;
}
