// 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.

import 'package:analysis_server/src/services/index/index.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/summary/idl.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'package:typed_mock/typed_mock.dart';

import '../../abstract_single_unit.dart';

main() {
  defineReflectiveSuite(() {
    defineReflectiveTests(IndexTest);
  });
}

@reflectiveTest
class IndexTest extends AbstractSingleUnitTest {
  Index index = createMemoryIndex();

  /**
   * Return the [Location] with given properties, or fail.
   */
  Location findLocation(List<Location> locations, String libraryUri,
      String unitUri, int offset, int length, bool isQualified) {
    for (Location location in locations) {
      if (location.libraryUri == libraryUri &&
          location.unitUri == unitUri &&
          location.offset == offset &&
          location.length == length &&
          location.isQualified == isQualified) {
        return location;
      }
    }
    fail('No at $offset with length $length qualified=$isQualified in\n'
        '${locations.join('\n')}');
    return null;
  }

  /**
   * Return the [Location] with given properties, or fail.
   */
  Location findLocationSource(
      List<Location> locations, Source source, String search, bool isQualified,
      {int length}) {
    String code = source.contents.data;
    int offset = code.indexOf(search);
    expect(offset, isNonNegative, reason: 'Not found "$search" in\n$code');
    length ??= getLeadingIdentifierLength(search);
    String uri = source.uri.toString();
    return findLocation(locations, uri, uri, offset, length, isQualified);
  }

  /**
   * Return the [Location] with given properties, or fail.
   */
  Location findLocationTest(
      List<Location> locations, String search, bool isQualified,
      {int length}) {
    int offset = findOffset(search);
    length ??= getLeadingIdentifierLength(search);
    String testUri = testSource.uri.toString();
    return findLocation(
        locations, testUri, testUri, offset, length, isQualified);
  }

  void setUp() {
    super.setUp();
  }

  void tearDown() {
    super.tearDown();
    index = null;
  }

  test_getDefinedNames_classMember() async {
    _indexTestUnit('''
class A {
  test() {}
}
class B {
  int test = 1;
  main() {
    int test = 2;
  }
}
''');
    ClassElement classA = findElement('A');
    ClassElement classB = findElement('B');
    List<Location> locations = await index.getDefinedNames(
        new RegExp(r'^test$'), IndexNameKind.classMember);
    expect(locations, hasLength(2));
    _assertHasDefinedName(locations, classA.methods[0]);
    _assertHasDefinedName(locations, classB.fields[0]);
  }

  test_getDefinedNames_topLevel() async {
    _indexTestUnit('''
class A {} // A
class B = Object with A;
typedef C();
D() {}
var E = null;
class NoMatchABCDE {}
''');
    Element topA = findElement('A');
    Element topB = findElement('B');
    Element topC = findElement('C');
    Element topD = findElement('D');
    Element topE = findElement('E');
    List<Location> locations = await index.getDefinedNames(
        new RegExp(r'^[A-E]$'), IndexNameKind.topLevel);
    expect(locations, hasLength(5));
    _assertHasDefinedName(locations, topA);
    _assertHasDefinedName(locations, topB);
    _assertHasDefinedName(locations, topC);
    _assertHasDefinedName(locations, topD);
    _assertHasDefinedName(locations, topE);
  }

  test_getDefinedNames_topLevel2() async {
    _indexTestUnit(
        '''
class A {} // A
class B = Object with A;
class NoMatchABCDE {}
''',
        declOnly: true);
    Element topA = findElement('A');
    Element topB = findElement('B');
    List<Location> locations = await index.getDefinedNames(
        new RegExp(r'^[A-E]$'), IndexNameKind.topLevel);
    expect(locations, hasLength(2));
    _assertHasDefinedName(locations, topA);
    _assertHasDefinedName(locations, topB);
  }

  test_getRelations_isExtendedBy() async {
    _indexTestUnit(r'''
class A {}
class B extends A {} // B
''');
    Source source2 = _indexUnit(
        '/test2.dart',
        r'''
import 'test.dart';
class C extends A {} // C
''');
    ClassElement elementA = testUnitElement.getType('A');
    List<Location> locations =
        await index.getRelations(elementA, IndexRelationKind.IS_EXTENDED_BY);
    findLocationTest(locations, 'A {} // B', false);
    findLocationSource(locations, source2, 'A {} // C', false);
  }

  test_getRelations_isReferencedBy() async {
    _indexTestUnit(r'''
main(int a, int b) {
}
''');
    ClassElement intElement = context.typeProvider.intType.element;
    List<Location> locations = await index.getRelations(
        intElement, IndexRelationKind.IS_REFERENCED_BY);
    findLocationTest(locations, 'int a', false);
    findLocationTest(locations, 'int b', false);
  }

  test_getUnresolvedMemberReferences_qualified_resolved() async {
    _indexTestUnit('''
class A {
  var test; // A
}
main(A a) {
  print(a.test);
  a.test = 1;
  a.test += 2;
  a.test();
}
''');
    List<Location> locations =
        await index.getUnresolvedMemberReferences('test');
    expect(locations, isEmpty);
  }

  test_getUnresolvedMemberReferences_qualified_unresolved() async {
    _indexTestUnit('''
class A {
  var test; // A
}
main(p) {
  print(p.test);
  p.test = 1;
  p.test += 2;
  p.test();
  print(p.test2); // not requested
}
''');
    List<Location> locations =
        await index.getUnresolvedMemberReferences('test');
    expect(locations, hasLength(4));
    findLocationTest(locations, 'test);', true);
    findLocationTest(locations, 'test = 1;', true);
    findLocationTest(locations, 'test += 2;', true);
    findLocationTest(locations, 'test();', true);
  }

  test_getUnresolvedMemberReferences_unqualified_resolved() async {
    _indexTestUnit('''
class A {
  var test;
  m() {
    print(test);
    test = 1;
    test += 2;
    test();
  }
}
''');
    List<Location> locations =
        await index.getUnresolvedMemberReferences('test');
    expect(locations, isEmpty);
  }

  test_getUnresolvedMemberReferences_unqualified_unresolved() async {
    verifyNoTestUnitErrors = false;
    _indexTestUnit('''
class A {
  m() {
    print(test);
    test = 1;
    test += 2;
    test();
    print(test2); // not requested
  }
}
''');
    List<Location> locations =
        await index.getUnresolvedMemberReferences('test');
    expect(locations, hasLength(4));
    findLocationTest(locations, 'test);', false);
    findLocationTest(locations, 'test = 1;', false);
    findLocationTest(locations, 'test += 2;', false);
    findLocationTest(locations, 'test();', false);
  }

  test_indexDeclarations_afterIndexUnit() async {
    resolveTestUnit('''
var a = 0;
var b = a + 1;
''');
    index.indexUnit(testUnit);
    TopLevelVariableElement a = findElement('a');
    // We can find references.
    {
      List<Location> locations = await index.getRelations(
          a.getter, IndexRelationKind.IS_REFERENCED_BY);
      findLocationTest(locations, 'a + 1', false);
    }
    // Attempt to index just declarations - we still can find references.
    index.indexDeclarations(testUnit);
    {
      List<Location> locations = await index.getRelations(
          a.getter, IndexRelationKind.IS_REFERENCED_BY);
      findLocationTest(locations, 'a + 1', false);
    }
  }

  test_indexDeclarations_nullUnit() async {
    index.indexDeclarations(null);
  }

  test_indexDeclarations_nullUnitElement() async {
    resolveTestUnit('');
    testUnit.element = null;
    index.indexDeclarations(testUnit);
  }

  test_indexUnit_nullLibraryElement() async {
    resolveTestUnit('');
    CompilationUnitElement unitElement = new _CompilationUnitElementMock();
    expect(unitElement.library, isNull);
    testUnit.element = unitElement;
    index.indexUnit(testUnit);
  }

  test_indexUnit_nullUnit() async {
    index.indexUnit(null);
  }

  test_indexUnit_nullUnitElement() async {
    resolveTestUnit('');
    testUnit.element = null;
    index.indexUnit(testUnit);
  }

  test_removeContext() async {
    _indexTestUnit('''
class A {}
''');
    RegExp regExp = new RegExp(r'^A$');
    expect(await index.getDefinedNames(regExp, IndexNameKind.topLevel),
        hasLength(1));
    // remove the context - no top-level declarations
    index.removeContext(context);
    expect(
        await index.getDefinedNames(regExp, IndexNameKind.topLevel), isEmpty);
  }

  test_removeUnit() async {
    RegExp regExp = new RegExp(r'^[AB]$');
    Source sourceA = addSource('/a.dart', 'class A {}');
    Source sourceB = addSource('/b.dart', 'class B {}');
    CompilationUnit unitA = resolveLibraryUnit(sourceA);
    CompilationUnit unitB = resolveLibraryUnit(sourceB);
    index.indexUnit(unitA);
    index.indexUnit(unitB);
    {
      List<Location> locations =
          await index.getDefinedNames(regExp, IndexNameKind.topLevel);
      expect(locations, hasLength(2));
      expect(locations.map((l) => l.libraryUri),
          unorderedEquals([sourceA.uri.toString(), sourceB.uri.toString()]));
    }
    // remove a.dart - no a.dart location
    index.removeUnit(context, sourceA, sourceA);
    {
      List<Location> locations =
          await index.getDefinedNames(regExp, IndexNameKind.topLevel);
      expect(locations, hasLength(1));
      expect(locations.map((l) => l.libraryUri),
          unorderedEquals([sourceB.uri.toString()]));
    }
  }

  /**
   * Assert that the given list of [locations] has a [Location] corresponding
   * to the [element].
   */
  void _assertHasDefinedName(List<Location> locations, Element element) {
    String libraryUri = element.library.source.uri.toString();
    String unitUri = element.source.uri.toString();
    for (Location location in locations) {
      if (location.libraryUri == libraryUri &&
          location.unitUri == unitUri &&
          location.offset == element.nameOffset &&
          location.length == element.nameLength) {
        return;
      }
    }
    fail('No declaration of $element at ${element.nameOffset} in\n'
        '${locations.join('\n')}');
  }

  void _indexTestUnit(String code, {bool declOnly: false}) {
    resolveTestUnit(code);
    if (declOnly) {
      index.indexDeclarations(testUnit);
    } else {
      index.indexUnit(testUnit);
    }
  }

  Source _indexUnit(String path, String code) {
    Source source = addSource(path, code);
    CompilationUnit unit = resolveLibraryUnit(source);
    index.indexUnit(unit);
    return source;
  }
}

class _CompilationUnitElementMock extends TypedMock
    implements CompilationUnitElement {}
