// 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/file_system/file_system.dart';
import 'package:analyzer/file_system/memory_file_system.dart';
import 'package:analyzer/source/package_map_resolver.dart';
import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/source.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';

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

@reflectiveTest
class SearchEngineImplTest {
  final MemoryResourceProvider provider = new MemoryResourceProvider();
  DartSdk sdk;
  final ByteStore byteStore = new MemoryByteStore();
  final FileContentOverlay contentOverlay = new FileContentOverlay();

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

  AnalysisDriverScheduler scheduler;

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

  test_membersOfSubtypes_hasMembers() async {
    var a = _p('/test/a.dart');
    var b = _p('/test/b.dart');
    var c = _p('/test/c.dart');

    provider.newFile(a, '''
class A {
  void a() {}
  void b() {}
  void c() {}
}
''');
    provider.newFile(b, '''
import 'a.dart';
class B extends A {
  void a() {}
}
''');
    provider.newFile(c, '''
import 'a.dart';
class C extends A {
  void b() {}
}
''');

    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.element.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 = _p('/test/a.dart');
    var b = _p('/test/b.dart');

    provider.newFile(a, '''
class A {
  void a() {}
  void b() {}
  void c() {}
}
''');
    provider.newFile(b, '''
import 'a.dart';
class B extends A {}
''');

    var driver = _newDriver();

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

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

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

  test_membersOfSubtypes_noSubtypes() async {
    var a = _p('/test/a.dart');
    var b = _p('/test/b.dart');

    provider.newFile(a, '''
class A {
  void a() {}
  void b() {}
  void c() {}
}
''');
    provider.newFile(b, '''
import 'a.dart';
class B {
  void a() {}
}
''');

    var driver = _newDriver();

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

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

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

  test_membersOfSubtypes_private() async {
    var a = _p('/test/a.dart');
    var b = _p('/test/b.dart');

    provider.newFile(a, '''
class A {
  void a() {}
  void _b() {}
  void _c() {}
}
class B extends A {
  void _b() {}
}
''');
    provider.newFile(b, '''
import 'a.dart';
class C extends A {
  void a() {}
  void _c() {}
}
class D extends B {
  void _c() {}
}
''');

    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.element.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 = _p('/test.dart');

    provider.newFile(p, '''
class T {}
class A extends T {}
class B extends A {}
class C implements B {}
''');

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

    var resultA = await driver.getResult(p);
    ClassElement element = resultA.unit.element.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 = _p('/test/a.dart');
    var b = _p('/test/b.dart');

    provider.newFile(a, '''
class T {}
class A extends T {}
''');
    provider.newFile(b, '''
import 'a.dart';
class B extends A {}
class C extends B {}
''');

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

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

    var resultA = await driver1.getResult(a);
    ClassElement element = resultA.unit.element.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 a = _p('/test/a.dart');
    var b = _p('/test/b.dart');

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

    provider.newFile(a, codeA);
    provider.newFile(b, codeB);

    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 = _p('/test/a.dart');
    var b = _p('/test/b.dart');

    provider.newFile(a, '''
class A {
  int test;
}
foo(p) {
  p.test;
}
''');
    provider.newFile(b, '''
import 'a.dart';
bar(p) {
  p.test = 1;
}
''');

    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 = _p('/test/a.dart');
    var b = _p('/test/b.dart');

    provider.newFile(a, '''
class T {}
T a;
''');
    provider.newFile(b, '''
import 'a.dart';
T b;
''');

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

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

    var resultA = await driver1.getResult(a);
    ClassElement element = resultA.unit.element.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_searchTopLevelDeclarations() async {
    var a = _p('/test/a.dart');
    var b = _p('/test/b.dart');

    provider.newFile(a, '''
class A {}
int a;
''');
    provider.newFile(b, '''
class B {}
get b => 42;
''');

    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 = _p('/a/lib/a.dart');
    provider.newFile(a, '''
class A {}
''');
    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 = _p('/b/lib/b.dart');
    provider.newFile(b, '''
import 'package:a/a.dart';
class B extends A {}
''');
    var driver2 = _newDriver(
        packageUriResolver: new PackageMapUriResolver(provider, {
      'a': [provider.getFile(a).parent]
    }));
    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('.*');
    // 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');
  }

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

    return new AnalysisDriver(
        scheduler,
        logger,
        provider,
        byteStore,
        contentOverlay,
        null,
        new SourceFactory(resolvers, null, provider),
        new AnalysisOptionsImpl()..strongMode = true);
  }

  String _p(String path) => provider.convertPath(path);
}
