// 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 'dart:async';

import 'package:analysis_server/src/services/search/search_engine.dart';
import 'package:analysis_server/src/services/search/search_engine_internal.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/file_system/file_system.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/source/package_map_resolver.dart';
import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
import 'package:front_end/src/api_prototype/byte_store.dart';
import 'package:front_end/src/base/performance_logger.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

import '../../mock_sdk.dart';
import '../../test_utilities/utillities.dart';

main() {
  defineReflectiveSuite(() {
    defineReflectiveTests(SearchEngineImplTest);
    defineReflectiveTests(SearchEngineImplTest_UseCFE);
  });
}

@reflectiveTest
class SearchEngineImplTest extends Object with ResourceProviderMixin {
  DartSdk sdk;
  final ByteStore byteStore = new MemoryByteStore();
  final FileContentOverlay contentOverlay = new FileContentOverlay();

  final StringBuffer logBuffer = new StringBuffer();
  PerformanceLog logger;

  AnalysisDriverScheduler scheduler;

  /**
   * Return `true` to enable the Dart 2.0 Common Front End.
   */
  bool get useCFE => false;

  void setUp() {
    sdk = new MockSdk(resourceProvider: resourceProvider);
    logger = new PerformanceLog(logBuffer);
    scheduler = new AnalysisDriverScheduler(logger);
    scheduler.start();
  }

  test_membersOfSubtypes_hasMembers() async {
    var a = newFile('/test/a.dart', content: '''
class A {
  void a() {}
  void b() {}
  void c() {}
}
''').path;
    var b = newFile('/test/b.dart', content: '''
import 'a.dart';
class B extends A {
  void a() {}
}
''').path;
    var c = newFile('/test/c.dart', content: '''
import 'a.dart';
class C extends A {
  void b() {}
}
''').path;

    var driver1 = _newDriver();
    var driver2 = _newDriver();

    driver1.addFile(a);
    driver2.addFile(b);
    driver2.addFile(c);
    await scheduler.waitForIdle();

    var resultA = await driver1.getResult(a);
    ClassElement elementA = resultA.unit.declaredElement.types[0];

    var searchEngine = new SearchEngineImpl([driver1, driver2]);
    Set<String> members = await searchEngine.membersOfSubtypes(elementA);
    expect(members, unorderedEquals(['a', 'b']));
  }

  test_membersOfSubtypes_noMembers() async {
    var a = newFile('/test/a.dart', content: '''
class A {
  void a() {}
  void b() {}
  void c() {}
}
''').path;
    var b = newFile('/test/b.dart', content: '''
import 'a.dart';
class B extends A {}
''').path;

    var driver = _newDriver();

    driver.addFile(a);
    driver.addFile(b);
    await scheduler.waitForIdle();

    var resultA = await driver.getResult(a);
    ClassElement elementA = resultA.unit.declaredElement.types[0];

    var searchEngine = new SearchEngineImpl([driver]);
    Set<String> members = await searchEngine.membersOfSubtypes(elementA);
    expect(members, isEmpty);
  }

  test_membersOfSubtypes_noSubtypes() async {
    var a = newFile('/test/a.dart', content: '''
class A {
  void a() {}
  void b() {}
  void c() {}
}
''').path;
    var b = newFile('/test/b.dart', content: '''
import 'a.dart';
class B {
  void a() {}
}
''').path;

    var driver = _newDriver();

    driver.addFile(a);
    driver.addFile(b);
    await scheduler.waitForIdle();

    var resultA = await driver.getResult(a);
    ClassElement elementA = resultA.unit.declaredElement.types[0];

    var searchEngine = new SearchEngineImpl([driver]);
    Set<String> members = await searchEngine.membersOfSubtypes(elementA);
    expect(members, isNull);
  }

  test_membersOfSubtypes_private() async {
    var a = newFile('/test/a.dart', content: '''
class A {
  void a() {}
  void _b() {}
  void _c() {}
}
class B extends A {
  void _b() {}
}
''').path;
    var b = newFile('/test/b.dart', content: '''
import 'a.dart';
class C extends A {
  void a() {}
  void _c() {}
}
class D extends B {
  void _c() {}
}
''').path;

    var driver1 = _newDriver();
    var driver2 = _newDriver();

    driver1.addFile(a);
    driver2.addFile(b);
    await scheduler.waitForIdle();

    var resultA = await driver1.getResult(a);
    ClassElement elementA = resultA.unit.declaredElement.types[0];

    var searchEngine = new SearchEngineImpl([driver1, driver2]);
    Set<String> members = await searchEngine.membersOfSubtypes(elementA);
    expect(members, unorderedEquals(['a', '_b']));
  }

  test_searchAllSubtypes() async {
    var p = newFile('/test.dart', content: '''
class T {}
class A extends T {}
class B extends A {}
class C implements B {}
''').path;

    var driver = _newDriver();
    driver.addFile(p);

    var resultA = await driver.getResult(p);
    ClassElement element = resultA.unit.declaredElement.types[0];

    var searchEngine = new SearchEngineImpl([driver]);
    Set<ClassElement> subtypes = await searchEngine.searchAllSubtypes(element);
    expect(subtypes, hasLength(3));
    expect(subtypes, contains(predicate((ClassElement e) => e.name == 'A')));
    expect(subtypes, contains(predicate((ClassElement e) => e.name == 'B')));
    expect(subtypes, contains(predicate((ClassElement e) => e.name == 'C')));
  }

  test_searchAllSubtypes_acrossDrivers() async {
    var a = newFile('/test/a.dart', content: '''
class T {}
class A extends T {}
''').path;
    var b = newFile('/test/b.dart', content: '''
import 'a.dart';
class B extends A {}
class C extends B {}
''').path;

    var driver1 = _newDriver();
    var driver2 = _newDriver();

    driver1.addFile(a);
    driver2.addFile(b);

    var resultA = await driver1.getResult(a);
    ClassElement element = resultA.unit.declaredElement.types[0];

    var searchEngine = new SearchEngineImpl([driver1, driver2]);
    Set<ClassElement> subtypes = await searchEngine.searchAllSubtypes(element);
    expect(subtypes, hasLength(3));
    expect(subtypes, contains(predicate((ClassElement e) => e.name == 'A')));
    expect(subtypes, contains(predicate((ClassElement e) => e.name == 'B')));
    expect(subtypes, contains(predicate((ClassElement e) => e.name == 'C')));
  }

  test_searchMemberDeclarations() async {
    var codeA = '''
class A {
  int test; // 1
  int testTwo;
}
''';
    var codeB = '''
class B {
  void test() {} // 2
  void testTwo() {}
}
int test;
''';

    var a = newFile('/test/a.dart', content: codeA).path;
    var b = newFile('/test/b.dart', content: codeB).path;

    var driver1 = _newDriver();
    var driver2 = _newDriver();

    driver1.addFile(a);
    driver2.addFile(b);

    while (scheduler.isAnalyzing) {
      await new Future.delayed(new Duration(milliseconds: 1));
    }

    var searchEngine = new SearchEngineImpl([driver1, driver2]);
    List<SearchMatch> matches =
        await searchEngine.searchMemberDeclarations('test');
    expect(matches, hasLength(2));

    void assertHasElement(String name, int nameOffset) {
      expect(
          matches,
          contains(predicate((SearchMatch m) =>
              m.kind == MatchKind.DECLARATION &&
              m.element.name == name &&
              m.element.nameOffset == nameOffset)));
    }

    assertHasElement('test', codeA.indexOf('test; // 1'));
    assertHasElement('test', codeB.indexOf('test() {} // 2'));
  }

  test_searchMemberReferences() async {
    var a = newFile('/test/a.dart', content: '''
class A {
  int test;
}
foo(p) {
  p.test;
}
''').path;
    var b = newFile('/test/b.dart', content: '''
import 'a.dart';
bar(p) {
  p.test = 1;
}
''').path;

    var driver1 = _newDriver();
    var driver2 = _newDriver();

    driver1.addFile(a);
    driver2.addFile(b);

    var searchEngine = new SearchEngineImpl([driver1, driver2]);
    List<SearchMatch> matches =
        await searchEngine.searchMemberReferences('test');
    expect(matches, hasLength(2));
    expect(
        matches,
        contains(predicate((SearchMatch m) =>
            m.element.name == 'foo' || m.kind == MatchKind.READ)));
    expect(
        matches,
        contains(predicate((SearchMatch m) =>
            m.element.name == 'bar' || m.kind == MatchKind.WRITE)));
  }

  test_searchReferences() async {
    var a = newFile('/test/a.dart', content: '''
class T {}
T a;
''').path;
    var b = newFile('/test/b.dart', content: '''
import 'a.dart';
T b;
''').path;

    var driver1 = _newDriver();
    var driver2 = _newDriver();

    driver1.addFile(a);
    driver2.addFile(b);

    var resultA = await driver1.getResult(a);
    ClassElement element = resultA.unit.declaredElement.types[0];

    var searchEngine = new SearchEngineImpl([driver1, driver2]);
    List<SearchMatch> matches = await searchEngine.searchReferences(element);
    expect(matches, hasLength(2));
    expect(
        matches, contains(predicate((SearchMatch m) => m.element.name == 'a')));
    expect(
        matches, contains(predicate((SearchMatch m) => m.element.name == 'b')));
  }

  test_searchReferences_discover_owned() async {
    var t = newFile('/test/lib/t.dart', content: '''
import 'package:aaa/a.dart';
int t;
''').path;
    var a = newFile('/aaa/lib/a.dart', content: '''
int a;
''').path;

    var driver1 = _newDriver(packageUriResolver: _mapUriResolver('aaa', a));
    var driver2 = _newDriver();

    driver1.addFile(t);
    driver2.addFile(a);

    LibraryElement coreLib = await driver1.getLibraryByUri('dart:core');
    ClassElement intElement = coreLib.getType('int');

    var searchEngine = new SearchEngineImpl([driver1, driver2]);
    var matches = await searchEngine.searchReferences(intElement);

    void assertHasOne(String path, String name) {
      expect(matches.where((m) {
        var element = m.element;
        return element.name == name && element.source.fullName == path;
      }), hasLength(1));
    }

    assertHasOne(t, 't');
    assertHasOne(a, 'a');
  }

  test_searchTopLevelDeclarations() async {
    var a = newFile('/test/a.dart', content: '''
class A {}
int a;
''').path;
    var b = newFile('/test/b.dart', content: '''
class B {}
get b => 42;
''').path;

    var driver1 = _newDriver();
    var driver2 = _newDriver();

    driver1.addFile(a);
    driver2.addFile(b);

    while (scheduler.isAnalyzing) {
      await new Future.delayed(new Duration(milliseconds: 1));
    }

    var searchEngine = new SearchEngineImpl([driver1, driver2]);
    List<SearchMatch> matches =
        await searchEngine.searchTopLevelDeclarations('.*');
    expect(
        matches.where((match) => !match.libraryElement.isInSdk), hasLength(4));

    void assertHasOneElement(String name) {
      Iterable<SearchMatch> nameMatches = matches.where((SearchMatch m) =>
          m.kind == MatchKind.DECLARATION && m.element.name == name);
      expect(nameMatches, hasLength(1));
    }

    assertHasOneElement('A');
    assertHasOneElement('a');
    assertHasOneElement('B');
    assertHasOneElement('b');
  }

  test_searchTopLevelDeclarations_dependentPackage() async {
    var a = newFile('/a/lib/a.dart', content: '''
class A {}
''').path;
    var driver1 = _newDriver();
    driver1.addFile(a);

    // The package:b uses the class A from the package:a,
    // so it sees the declaration the element A.
    var b = newFile('/b/lib/b.dart', content: '''
import 'package:a/a.dart';
class B extends A {}
''');
    var driver2 = _newDriver(packageUriResolver: _mapUriResolver('a', a));
    driver2.addFile(b.path);

    while (scheduler.isAnalyzing) {
      await new Future.delayed(new Duration(milliseconds: 1));
    }

    var searchEngine = new SearchEngineImpl([driver1, driver2]);
    List<SearchMatch> matches =
        await searchEngine.searchTopLevelDeclarations('.*');
    // We get exactly two items: A and B.
    // I.e. we get exactly one A.
    expect(
        matches.where((match) => !match.libraryElement.isInSdk), hasLength(2));

    void assertHasOneElement(String name) {
      Iterable<SearchMatch> nameMatches = matches.where((SearchMatch m) =>
          m.kind == MatchKind.DECLARATION && m.element.name == name);
      expect(nameMatches, hasLength(1));
    }

    assertHasOneElement('A');
    assertHasOneElement('B');
  }

  UriResolver _mapUriResolver(String packageName, String path) {
    return new PackageMapUriResolver(resourceProvider, {
      packageName: [resourceProvider.getFile(path).parent]
    });
  }

  AnalysisDriver _newDriver({UriResolver packageUriResolver}) {
    var resolvers = <UriResolver>[
      new DartUriResolver(sdk),
      new ResourceUriResolver(resourceProvider)
    ];
    if (packageUriResolver != null) {
      resolvers.add(packageUriResolver);
    }
    resolvers.add(new ResourceUriResolver(resourceProvider));

    return new AnalysisDriver(
        scheduler,
        logger,
        resourceProvider,
        byteStore,
        contentOverlay,
        null,
        new SourceFactory(resolvers, null, resourceProvider),
        new AnalysisOptionsImpl(),
        useCFE: useCFE);
  }
}

@reflectiveTest
class SearchEngineImplTest_UseCFE extends SearchEngineImplTest {
  @override
  bool get useCFE => true;

  @failingTest
  @override
  test_searchAllSubtypes() => super.test_searchAllSubtypes();

  @failingTest
  @override
  test_searchAllSubtypes_acrossDrivers() =>
      super.test_searchAllSubtypes_acrossDrivers();

  @failingTest
  @override
  test_searchMemberReferences() =>
      callFailingTest(super.test_searchMemberReferences());

  @failingTest
  @override
  test_searchReferences() => super.test_searchReferences();

  @failingTest
  @override
  test_searchReferences_discover_owned() {
    return callFailingTest(super.test_searchReferences_discover_owned);
  }
}
