// Copyright (c) 2012, 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.

import "package:expect/expect.dart";
import "package:async_helper/async_helper.dart";
import 'compiler_helper.dart';
import 'parser_helper.dart';

void checkPosition(Spannable spannable, Node node, String source, compiler) {
  SourceSpan span = compiler.spanFromSpannable(spannable);
  Expect.isTrue(span.begin < span.end,
                'begin = ${span.begin}; end = ${span.end}');
  Expect.isTrue(span.end < source.length,
                'end = ${span.end}; length = ${source.length}');
  String yield = source.substring(span.begin, span.end);

  // TODO(ahe): The node does not include "@". Fix that.
  Expect.stringEquals('@$node', yield);
}

void checkAnnotation(String name, String declaration,
                     {bool isTopLevelOnly: false}) {
  // Ensure that a compile-time constant can be resolved from an
  // annotation.
  var source1 = """const native = 'xyz';
                   @native
                   $declaration
                   main() {}""";

  compileAndCheck(source1, name, (compiler, element) {
    compiler.enqueuer.resolution.queueIsClosed = false;
    Expect.equals(1, length(element.metadata));
    PartialMetadataAnnotation annotation = element.metadata.head;
    annotation.ensureResolved(compiler);
    Constant value = annotation.value;
    Expect.stringEquals('xyz', value.value.slowToString());

    checkPosition(annotation, annotation.cachedNode, source1, compiler);
  });

  // Ensure that each repeated annotation has a unique instance of
  // [MetadataAnnotation].
  var source2 = """const native = 'xyz';
                   @native @native
                   $declaration
                   main() {}""";

  compileAndCheck(source2, name, (compiler, element) {
    compiler.enqueuer.resolution.queueIsClosed = false;
    Expect.equals(2, length(element.metadata));
    PartialMetadataAnnotation annotation1 = element.metadata.head;
    PartialMetadataAnnotation annotation2 = element.metadata.tail.head;
    annotation1.ensureResolved(compiler);
    annotation2.ensureResolved(compiler);
    Expect.isFalse(identical(annotation1, annotation2),
                   'expected unique instances');
    Expect.notEquals(annotation1, annotation2, 'expected unequal instances');
    Constant value1 = annotation1.value;
    Constant value2 = annotation2.value;
    Expect.identical(value1, value2, 'expected same compile-time constant');
    Expect.stringEquals('xyz', value1.value.slowToString());
    Expect.stringEquals('xyz', value2.value.slowToString());

    checkPosition(annotation1, annotation1.cachedNode, source2, compiler);
    checkPosition(annotation2, annotation2.cachedNode, source2, compiler);
  });

  if (isTopLevelOnly) return;

  // Ensure that a compile-time constant can be resolved from an
  // annotation.
  var source3 = """const native = 'xyz';
                   class Foo {
                     @native
                     $declaration
                   }
                   main() {}""";

  compileAndCheck(source3, 'Foo', (compiler, element) {
    compiler.enqueuer.resolution.queueIsClosed = false;
    Expect.equals(0, length(element.metadata));
    element.ensureResolved(compiler);
    Expect.equals(0, length(element.metadata));
    element = element.lookupLocalMember(buildSourceString(name));
    Expect.equals(1, length(element.metadata));
    PartialMetadataAnnotation annotation = element.metadata.head;
    annotation.ensureResolved(compiler);
    Constant value = annotation.value;
    Expect.stringEquals('xyz', value.value.slowToString());

    checkPosition(annotation, annotation.cachedNode, source3, compiler);
  });

  // Ensure that each repeated annotation has a unique instance of
  // [MetadataAnnotation].
  var source4 = """const native = 'xyz';
                   class Foo {
                     @native @native
                     $declaration
                   }
                   main() {}""";

  compileAndCheck(source4, 'Foo', (compiler, element) {
    compiler.enqueuer.resolution.queueIsClosed = false;
    Expect.equals(0, length(element.metadata));
    element.ensureResolved(compiler);
    Expect.equals(0, length(element.metadata));
    element = element.lookupLocalMember(buildSourceString(name));
    Expect.equals(2, length(element.metadata));
    PartialMetadataAnnotation annotation1 = element.metadata.head;
    PartialMetadataAnnotation annotation2 = element.metadata.tail.head;
    annotation1.ensureResolved(compiler);
    annotation2.ensureResolved(compiler);
    Expect.isFalse(identical(annotation1, annotation2),
                   'expected unique instances');
    Expect.notEquals(annotation1, annotation2, 'expected unequal instances');
    Constant value1 = annotation1.value;
    Constant value2 = annotation2.value;
    Expect.identical(value1, value2, 'expected same compile-time constant');
    Expect.stringEquals('xyz', value1.value.slowToString());
    Expect.stringEquals('xyz', value2.value.slowToString());

    checkPosition(annotation1, annotation1.cachedNode, source4, compiler);
    checkPosition(annotation1, annotation2.cachedNode, source4, compiler);
  });
}

void testClassMetadata() {
  checkAnnotation('Foo', 'class Foo {}', isTopLevelOnly: true);
}

void testTopLevelMethodMetadata() {
  checkAnnotation('foo', 'foo() {}');
}

void testTopLevelFieldMetadata() {
  checkAnnotation('foo', 'var foo;');
}

void testLibraryTags() {
  void compileAndCheckLibrary(
      String source,
      Link<MetadataAnnotation> extractMetadata(LibraryElement element)) {
    Uri partUri = new Uri(scheme: 'source', path: 'part.dart');
    String partSource = '@native part of foo;';

    Uri libUri = new Uri(scheme: 'source', path: 'lib.dart');
    String libSource = 'library lib;';

    Uri uri = new Uri(scheme: 'source', path: 'main.dart');

    Uri async = new Uri(scheme: 'dart', path: 'async');

    var compiler = compilerFor(source, uri)
        ..registerSource(partUri, partSource)
        ..registerSource(libUri, libSource)
        ..registerSource(async, 'class DeferredLibrary {}');

    asyncTest(() => compiler.runCompiler(uri).then((_) {
      compiler.enqueuer.resolution.queueIsClosed = false;
      LibraryElement element = compiler.libraries['$uri'];
      Expect.isNotNull(element, 'Cannot find $uri');

      Link<MetadataAnnotation> metadata = extractMetadata(element);
      Expect.equals(1, length(metadata));

      PartialMetadataAnnotation annotation = metadata.head;
      annotation.ensureResolved(compiler);
      Constant value = annotation.value;
      Expect.stringEquals('xyz', value.value.slowToString());

      checkPosition(annotation, annotation.cachedNode, source, compiler);
    }));
  }

  var source;

  source = """@native
              library foo;
              const native = 'xyz';
              main() {}""";
  compileAndCheckLibrary(source, (e) => e.libraryTag.metadata);

  source = """@native
              import 'lib.dart';
              const native = 'xyz';
              main() {}""";
  compileAndCheckLibrary(source, (e) => e.tags.single.metadata);

  source = """@native
              export 'lib.dart';
              const native = 'xyz';
              main() {}""";
  compileAndCheckLibrary(source, (e) => e.tags.single.metadata);

  source = """@native
              part 'part.dart';
              const native = 'xyz';
              main() {}""";
  compileAndCheckLibrary(source, (e) => e.tags.single.metadata);

  source = """@native
              part 'part.dart';
              const native = 'xyz';
              main() {}""";
  compileAndCheckLibrary(source,
                         (e) => e.compilationUnits.first.partTag.metadata);
}

void main() {
  testClassMetadata();
  testTopLevelMethodMetadata();
  testTopLevelFieldMetadata();
  testLibraryTags();
}
