// 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 parser_helper;

import "package:expect/expect.dart";

import "package:compiler/src/elements/elements.dart";
import "package:compiler/src/tree/tree.dart";
import "package:compiler/src/parser/element_listener.dart";
import "package:compiler/src/parser/node_listener.dart";
import "package:compiler/src/parser/parser.dart";
import "package:compiler/src/parser/partial_parser.dart";
import "package:compiler/src/scanner/string_scanner.dart";
import "package:compiler/src/tokens/token.dart";
import "package:compiler/src/tokens/token_constants.dart";
import "package:compiler/src/io/source_file.dart";
import "package:compiler/src/util/util.dart";

import "package:compiler/src/elements/modelx.dart"
    show CompilationUnitElementX, ElementX, LibraryElementX;

import "package:compiler/src/compiler.dart";
import 'package:compiler/src/options.dart';
import "package:compiler/src/diagnostics/source_span.dart";
import "package:compiler/src/diagnostics/spannable.dart";
import "package:compiler/src/diagnostics/diagnostic_listener.dart";
import "package:compiler/src/diagnostics/messages.dart";
import "package:compiler/src/script.dart";

import "options_helper.dart";

export "package:compiler/src/diagnostics/diagnostic_listener.dart";
export 'package:compiler/src/parser/listener.dart';
export 'package:compiler/src/parser/node_listener.dart';
export 'package:compiler/src/parser/parser.dart';
export 'package:compiler/src/parser/partial_parser.dart';
export 'package:compiler/src/parser/partial_elements.dart';
export "package:compiler/src/tokens/token.dart";
export "package:compiler/src/tokens/token_constants.dart";

class LoggerCanceler extends DiagnosticReporter {
  DiagnosticOptions get options => const MockDiagnosticOptions();

  void log(message) {
    print(message);
  }

  void internalError(node, String message) {
    log(message);
  }

  SourceSpan spanFromSpannable(node) {
    throw 'unsupported operation';
  }

  void reportError(
      DiagnosticMessage message,
      [List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) {
    log(message);
    infos.forEach(log);
  }

  void reportWarning(
      DiagnosticMessage message,
      [List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) {
    log(message);
    infos.forEach(log);
  }

  void reportInfo(Spannable node, MessageKind errorCode, [Map arguments]) {
    log(new Message(MessageTemplate.TEMPLATES[errorCode], arguments, false));
  }

  void reportHint(
      DiagnosticMessage message,
      [List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) {
    log(message);
    infos.forEach(log);
  }

  withCurrentElement(Element element, f()) => f();

  @override
  DiagnosticMessage createMessage(
      Spannable spannable,
      MessageKind messageKind,
      [Map arguments = const {}]) {
    return new DiagnosticMessage(
        null, spannable,
        new Message(MessageTemplate.TEMPLATES[messageKind], arguments, false));
  }
}

Token scan(String text) =>
    new StringScanner.fromString(text)
    .tokenize();

Node parseBodyCode(String text, Function parseMethod,
                   {DiagnosticReporter reporter}) {
  Token tokens = scan(text);
  if (reporter == null) reporter = new LoggerCanceler();
  Uri uri = new Uri(scheme: "source");
  Script script = new Script(uri, uri,new MockFile(text));
  LibraryElement library = new LibraryElementX(script);
  NodeListener listener = new NodeListener(
      new ScannerOptions(canUseNative: true),
      reporter, library.entryCompilationUnit);
  Parser parser = new Parser(listener, new MockParserOptions());
  Token endToken = parseMethod(parser, tokens);
  assert(endToken.kind == EOF_TOKEN);
  Node node = listener.popNode();
  Expect.isNotNull(node);
  Expect.isTrue(listener.nodes.isEmpty, 'Not empty: ${listener.nodes}');
  return node;
}

Node parseStatement(String text) =>
  parseBodyCode(text, (parser, tokens) => parser.parseStatement(tokens));

Node parseFunction(String text, Compiler compiler) {
  ElementX element = parseUnit(text, compiler, compiler.mainApp).head;
  Expect.isNotNull(element);
  Expect.equals(ElementKind.FUNCTION, element.kind);
  return element.parseNode(compiler.parsing);
}

Node parseMember(String text, {DiagnosticReporter reporter}) {
  return parseBodyCode(
      text,
      (parser, tokens) => parser.parseMember(tokens),
      reporter: reporter);
}

class MockFile extends StringSourceFile {
  MockFile(text)
      : super.fromName('<string>', text);
}

var sourceCounter = 0;

Link<Element> parseUnit(String text, Compiler compiler,
                        LibraryElement library,
                        [void registerSource(Uri uri, String source)]) {
  Token tokens = scan(text);
  Uri uri = new Uri(scheme: "source", path: '${++sourceCounter}');
  if (registerSource != null) {
    registerSource(uri, text);
  }
  var script = new Script(uri, uri, new MockFile(text));
  var unit = new CompilationUnitElementX(script, library);
  int id = 0;
  DiagnosticReporter reporter = compiler.reporter;
  ElementListener listener = new ElementListener(
      compiler.parsing.getScannerOptionsFor(library),
      reporter, unit, () => id++);
  PartialParser parser = new PartialParser(listener, new MockParserOptions());
  reporter.withCurrentElement(unit, () => parser.parseUnit(tokens));
  return unit.localMembers;
}

NodeList fullParseUnit(String source, {DiagnosticReporter reporter}) {
  return parseBodyCode(
      source,
      (parser, tokens) => parser.parseUnit(tokens),
      reporter: reporter);
}
