// 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 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.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 create(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 DeferredLoadTask {
  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;
}
