// 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:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/context/cache.dart';
import 'package:analyzer/src/dart/scanner/reader.dart';
import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/parser.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/summary/bazel_summary.dart';
import 'package:analyzer/src/summary/format.dart';
import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/summary/summarize_ast.dart';
import 'package:analyzer/src/summary/summarize_elements.dart';
import 'package:analyzer/src/util/fast_uri.dart';
import 'package:analyzer/task/dart.dart';
import 'package:path/path.dart' as pathos;
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

import '../context/abstract_context.dart';

main() {
  defineReflectiveSuite(() {
    defineReflectiveTests(BazelResultProviderTest);
    defineReflectiveTests(SummaryProviderTest);
  });
}

@reflectiveTest
class BazelResultProviderTest extends _BaseTest {
  BazelResultProvider provider;

  @override
  void setUp() {
    super.setUp();
    provider = new BazelResultProvider(new SummaryProvider(
        resourceProvider,
        '_.temp',
        _getOutputFolder,
        resourceProvider
            .getFolder(resourceProvider.convertPath('/tmp/dart/bazel/linked')),
        context));
  }

  test_failure_inconsistent_directDependency() {
    _setComponentFile('aaa', 'a.dart', 'class A {}');
    _setComponentFile(
        'bbb',
        'b.dart',
        r'''
import 'package:components.aaa/a.dart';
class B extends A {}
''');
    _writeUnlinkedBundle('components.aaa');
    _writeUnlinkedBundle('components.bbb');
    _setComponentFile('aaa', 'a.dart', 'class A2 {}');
    // The 'aaa' unlinked bundle in inconsistent, so 'bbb' linking fails.
    Source source = _resolveUri('package:components.bbb/b.dart');
    CacheEntry entry = context.getCacheEntry(source);
    expect(provider.compute(entry, LIBRARY_ELEMENT), isFalse);
  }

  test_failure_missingDirectDependency() {
    _setComponentFile('aaa', 'a.dart', 'class A {}');
    _setComponentFile(
        'bbb',
        'b.dart',
        r'''
import 'package:components.aaa/a.dart';
class B extends A {}
''');
    _writeUnlinkedBundle('components.bbb');
    // We cannot find 'aaa' bundle, so 'bbb' linking fails.
    Source source = _resolveUri('package:components.bbb/b.dart');
    CacheEntry entry = context.getCacheEntry(source);
    expect(provider.compute(entry, LIBRARY_ELEMENT), isFalse);
  }

  test_success_withoutDependencies() {
    _setComponentFile('aaa', 'a.dart', 'class A {}');
    _writeUnlinkedBundle('components.aaa');
    // Resynthesize 'aaa' library.
    Source source = _resolveUri('package:components.aaa/a.dart');
    LibraryElement library = _resynthesizeLibrary(source);
    List<ClassElement> types = library.definingCompilationUnit.types;
    expect(types, hasLength(1));
    expect(types.single.name, 'A');
  }

  test_withDependency_import() {
    _setComponentFile('aaa', 'a.dart', 'class A {}');
    _setComponentFile(
        'bbb',
        'b.dart',
        r'''
import 'package:components.aaa/a.dart';
class B extends A {}
''');
    _writeUnlinkedBundle('components.aaa');
    _writeUnlinkedBundle('components.bbb');
    // Prepare sources.
    Source sourceA = _resolveUri('package:components.aaa/a.dart');
    Source sourceB = _resolveUri('package:components.bbb/b.dart');
    // Resynthesize 'bbb' library.
    LibraryElement libraryB = _resynthesizeLibrary(sourceB);
    List<ClassElement> types = libraryB.definingCompilationUnit.types;
    expect(types, hasLength(1));
    ClassElement typeB = types.single;
    expect(typeB.name, 'B');
    expect(typeB.supertype.name, 'A');
    // The LibraryElement for 'aaa' is not created at all.
    expect(context.getResult(sourceA, LIBRARY_ELEMENT), isNull);
    // But we can resynthesize it, and it's the same as from 'bbb'.
    expect(provider.compute(context.getCacheEntry(sourceA), LIBRARY_ELEMENT),
        isTrue);
    LibraryElement libraryA = context.getResult(sourceA, LIBRARY_ELEMENT);
    expect(libraryA, isNotNull);
    expect(typeB.supertype.element.library, same(libraryA));
  }

  LibraryElement _resynthesizeLibrary(Source source) {
    CacheEntry entry = context.getCacheEntry(source);
    expect(provider.compute(entry, LIBRARY_ELEMENT), isTrue);
    return context.getResult(source, LIBRARY_ELEMENT);
  }
}

@reflectiveTest
class SummaryProviderTest extends _BaseTest {
  SummaryProvider manager;

  @override
  void setUp() {
    super.setUp();
    _createManager();
  }

  test_getLinkedPackages_cached() {
    _setComponentFile('aaa', 'a.dart', 'class A {}');
    _setComponentFile(
        'bbb',
        'b.dart',
        r'''
import 'package:components.aaa/a.dart';
class B extends A {}
''');
    _writeUnlinkedBundle('components.aaa');
    _writeUnlinkedBundle('components.bbb');
    Source source = _resolveUri('package:components.bbb/b.dart');

    // Session 1.
    // Create linked bundles and store them in files.
    {
      List<Package> packages = manager.getLinkedPackages(source);
      expect(packages, hasLength(2));
    }

    // Session 2.
    // Recreate manager (with disabled linking) and ask again.
    {
      _createManager(allowLinking: false);
      List<Package> packages = manager.getLinkedPackages(source);
      expect(packages, hasLength(2));
    }
  }

  test_getLinkedPackages_cached_declaredVariables_export() {
    _testImpl_getLinkedPackages_cached_declaredVariables('export');
  }

  test_getLinkedPackages_cached_declaredVariables_import() {
    _testImpl_getLinkedPackages_cached_declaredVariables('import');
  }

  test_getLinkedPackages_null_inconsistent_directDependency() {
    _setComponentFile('aaa', 'a.dart', 'class A {}');
    _setComponentFile(
        'bbb',
        'b.dart',
        r'''
import 'package:components.aaa/a.dart';
class B extends A {}
''');
    _writeUnlinkedBundle('components.aaa');
    _writeUnlinkedBundle('components.bbb');
    _setComponentFile('aaa', 'a.dart', 'class A2 {}');
    // The 'aaa' unlinked bundle in inconsistent, so 'bbb' linking fails.
    Source source = _resolveUri('package:components.bbb/b.dart');
    List<Package> packages = manager.getLinkedPackages(source);
    expect(packages, isNull);
  }

  test_getLinkedPackages_null_missingBundle() {
    _setComponentFile('aaa', 'a.dart', 'class A {}');
    // We don't write 'aaa', so we cannot get its package.
    // Ask the package for the URI.
    Source source = _resolveUri('package:components.aaa/a.dart');
    List<Package> packages = manager.getLinkedPackages(source);
    expect(packages, isNull);
  }

  test_getLinkedPackages_null_missingDirectDependency() {
    _setComponentFile('aaa', 'a.dart', 'class A {}');
    _setComponentFile(
        'bbb',
        'b.dart',
        r'''
import 'package:components.aaa/a.dart';
class B extends A {}
''');
    _writeUnlinkedBundle('components.bbb');
    // We cannot find 'aaa' bundle, so 'bbb' linking fails.
    Source source = _resolveUri('package:components.bbb/b.dart');
    List<Package> packages = manager.getLinkedPackages(source);
    expect(packages, isNull);
  }

  test_getLinkedPackages_null_missingIndirectDependency() {
    _setComponentFile('aaa', 'a.dart', 'class A {}');
    _setComponentFile(
        'bbb',
        'b.dart',
        r'''
import 'package:components.aaa/a.dart';
class B extends A {}
''');
    _setComponentFile(
        'ccc',
        'c.dart',
        r'''
import 'package:components.bbb/b.dart';
class C extends B {}
''');
    _writeUnlinkedBundle('components.bbb');
    _writeUnlinkedBundle('components.ccc');
    // We cannot find 'aaa' bundle, so 'ccc' linking fails.
    Source source = _resolveUri('package:components.ccc/c.dart');
    List<Package> packages = manager.getLinkedPackages(source);
    expect(packages, isNull);
  }

  test_getLinkedPackages_withDependency_export() {
    _setComponentFile('aaa', 'a.dart', 'class A {}');
    _setComponentFile(
        'bbb',
        'b.dart',
        r'''
export 'package:components.aaa/a.dart';
''');
    _writeUnlinkedBundle('components.aaa');
    _writeUnlinkedBundle('components.bbb');
    Source source = _resolveUri('package:components.bbb/b.dart');
    List<Package> packages = manager.getLinkedPackages(source);
    expect(packages, hasLength(2));
  }

  test_getLinkedPackages_withDependency_import() {
    _setComponentFile('aaa', 'a.dart', 'class A {}');
    _setComponentFile(
        'bbb',
        'b.dart',
        r'''
import 'package:components.aaa/a.dart';
class B extends A {}
''');
    _writeUnlinkedBundle('components.aaa');
    _writeUnlinkedBundle('components.bbb');
    Source source = _resolveUri('package:components.bbb/b.dart');
    List<Package> packages = manager.getLinkedPackages(source);
    expect(packages, hasLength(2));
  }

  test_getLinkedPackages_withDependency_import_cycle() {
    _setComponentFile(
        'aaa',
        'a.dart',
        r'''
import 'package:components.bbb/b.dart';
class A {}
class A2 extends B {}
''');
    _setComponentFile(
        'bbb',
        'b.dart',
        r'''
import 'package:components.aaa/a.dart';
class B extends A {}
class B2 extends A2 {}
''');
    _writeUnlinkedBundle('components.aaa');
    _writeUnlinkedBundle('components.bbb');
    Source source = _resolveUri('package:components.bbb/b.dart');
    List<Package> packages = manager.getLinkedPackages(source);
    expect(packages, hasLength(2));
  }

  test_getLinkedPackages_withDependency_import_indirect() {
    _setComponentFile('aaa', 'a.dart', 'class A {}');
    _setComponentFile(
        'bbb',
        'b.dart',
        r'''
import 'package:components.aaa/a.dart';
class B extends A {}
''');
    _setComponentFile(
        'ccc',
        'c.dart',
        r'''
import 'package:components.bbb/b.dart';
class C extends B {}
''');
    _writeUnlinkedBundle('components.aaa');
    _writeUnlinkedBundle('components.bbb');
    _writeUnlinkedBundle('components.ccc');
    Source source = _resolveUri('package:components.ccc/c.dart');
    List<Package> packages = manager.getLinkedPackages(source);
    expect(packages, hasLength(3));
  }

  test_getLinkedPackages_withoutDependencies() {
    _setComponentFile('aaa', 'a.dart', 'class A {}');
    _writeUnlinkedBundle('components.aaa');
    // Ask the package for the URI.
    Source source = _resolveUri('package:components.aaa/a.dart');
    List<Package> packages = manager.getLinkedPackages(source);
    expect(packages, hasLength(1));
  }

  test_getUnlinkedForUri() {
    _setComponentFile('aaa', 'a1.dart', 'class A1 {}');
    _setComponentFile('aaa', 'a2.dart', 'class A2 {}');
    _writeUnlinkedBundle('components.aaa');
    // Ask the package for the URI.
    Source source1 = _resolveUri('package:components.aaa/a1.dart');
    Source source2 = _resolveUri('package:components.aaa/a2.dart');
    Package package = manager.getUnlinkedForUri(source1.uri);
    expect(package, isNotNull);
    // The same instance is returned to another URI in the same package.
    expect(manager.getUnlinkedForUri(source2.uri), same(package));
  }

  test_getUnlinkedForUri_inconsistent_fileContent() {
    File file1 = _setComponentFile('aaa', 'a1.dart', 'class A1 {}');
    _setComponentFile('aaa', 'a2.dart', 'class A2 {}');
    _writeUnlinkedBundle('components.aaa');
    // Update one of the files, so the bundle is not consistent.
    file1.writeAsStringSync('\nclass A1 {}');
    Source source1 = _resolveUri('package:components.aaa/a1.dart');
    Source source2 = _resolveUri('package:components.aaa/a2.dart');
    expect(manager.getUnlinkedForUri(source1.uri), isNull);
    expect(manager.getUnlinkedForUri(source2.uri), isNull);
  }

  test_getUnlinkedForUri_inconsistent_majorVersion() {
    _setComponentFile('aaa', 'a.dart', 'class A {}');
    _writeUnlinkedBundle('components.aaa');
    Source source = _resolveUri('package:components.aaa/a.dart');

    // Create manager with a different major version.
    // The unlinked bundle cannot be used.
    _createManager(majorVersion: 12345);
    Package package = manager.getUnlinkedForUri(source.uri);
    expect(package, isNull);
  }

  void _createManager(
      {bool allowLinking: true,
      int majorVersion: PackageBundleAssembler.currentMajorVersion}) {
    manager = new SummaryProvider(resourceProvider, '_.temp', _getOutputFolder,
        resourceProvider.getFolder('/tmp/dart/bazel/linked'), context,
        allowLinking: allowLinking, majorVersion: majorVersion);
  }

  void _testImpl_getLinkedPackages_cached_declaredVariables(
      String importOrExport) {
    _setComponentFile(
        'aaa',
        'user.dart',
        '''
    $importOrExport 'foo.dart'
      if (dart.library.io) 'foo_io.dart'
      if (dart.library.html) 'foo_html.dart';
    ''');
    _setComponentFile('aaa', 'foo.dart', 'class B {}');
    _setComponentFile('aaa', 'foo_io.dart', 'class B {}');
    _setComponentFile('aaa', 'foo_dart.dart', 'class B {}');
    _writeUnlinkedBundle('components.aaa');
    Source source = _resolveUri('package:components.aaa/user.dart');

    void _assertDependencyInUser(PackageBundle bundle, String shortName) {
      for (var i = 0; i < bundle.linkedLibraryUris.length; i++) {
        if (bundle.linkedLibraryUris[i].endsWith('user.dart')) {
          LinkedLibrary library = bundle.linkedLibraries[i];
          expect(library.dependencies.map((d) => d.uri),
              unorderedEquals(['', 'dart:core', shortName]));
          return;
        }
      }
      fail('Not found user.dart in $bundle');
    }

    // Session 1.
    // Create linked bundles and store them in files.
    {
      List<Package> packages = manager.getLinkedPackages(source);
      expect(packages, hasLength(1));
      _assertDependencyInUser(packages.single.linked, 'foo.dart');
    }

    // Session 2.
    // Recreate manager and don't allow it to perform new linking.
    // Set a declared variable, which is not used in the package.
    // We still can get the cached linked bundle.
    {
      context.declaredVariables.define('not.used.variable', 'baz');
      _createManager(allowLinking: false);
      List<Package> packages = manager.getLinkedPackages(source);
      expect(packages, hasLength(1));
      _assertDependencyInUser(packages.single.linked, 'foo.dart');
    }

    // Session 3.
    // Recreate manager and don't allow it to perform new linking.
    // Set the value of a referenced declared variable.
    // So, we cannot use the previously cached linked bundle.
    {
      context.declaredVariables.define('dart.library.io', 'does-not-matter');
      _createManager(allowLinking: false);
      List<Package> packages = manager.getLinkedPackages(source);
      expect(packages, isEmpty);
    }

    // Session 4.
    // Enable new linking, and configure to use 'foo_html.dart'.
    {
      context.declaredVariables.define('dart.library.html', 'true');
      _createManager(allowLinking: true);
      List<Package> packages = manager.getLinkedPackages(source);
      expect(packages, hasLength(1));
      _assertDependencyInUser(packages.single.linked, 'foo_html.dart');
    }
  }
}

class _BaseTest extends AbstractContextTest {
  String sourceRoot;
  String outRoot;

  @override
  void setUp() {
    super.setUp();
    // Include a 'package' URI resolver.
    sourceRoot = resourceProvider.convertPath('/company/src/user/project/root');
    outRoot = resourceProvider.pathContext.join(sourceRoot, 'bazel-bin');
    sourceFactory = new SourceFactory(<UriResolver>[
      sdkResolver,
      resourceResolver,
      new _TestPackageResolver(resourceProvider, sourceRoot)
    ], null, resourceProvider);
    context.sourceFactory = sourceFactory;
  }

  Folder _getOutputFolder(Uri absoluteUri) {
    var pathContext = resourceProvider.pathContext;
    if (absoluteUri.scheme == 'package') {
      List<String> segments = absoluteUri.pathSegments;
      if (segments.isNotEmpty) {
        String packageName = segments.first;
        String path = pathContext.join(
            outRoot, packageName.replaceAll('.', pathContext.separator));
        return resourceProvider.getFolder(path);
      }
    }
    return null;
  }

  Source _resolveUri(String uri) {
    return context.sourceFactory.resolveUri(null, uri);
  }

  File _setComponentFile(String componentName, String fileName, String code) {
    String path = resourceProvider.pathContext
        .join(sourceRoot, 'components', componentName, 'lib', fileName);
    return resourceProvider.newFile(path, code);
  }

  void _writeUnlinkedBundle(String packageName) {
    var pathContext = resourceProvider.pathContext;
    String packagePath = packageName.replaceAll('.', pathContext.separator);
    PackageBundleBuilder unlinkedBundle = _computeUnlinkedBundle(
        resourceProvider,
        packageName,
        resourceProvider
            .getFolder(pathContext.join(sourceRoot, packagePath, 'lib')),
        true);
    String shortName = packageName.substring(packageName.lastIndexOf('.') + 1);
    resourceProvider.newFileWithBytes(
        pathContext.join(outRoot, packagePath, shortName) + '.full.ds',
        unlinkedBundle.toBuffer());
  }

  static PackageBundleBuilder _computeUnlinkedBundle(ResourceProvider provider,
      String packageName, Folder libFolder, bool strong) {
    var pathContext = provider.pathContext;
    String libPath = libFolder.path + pathContext.separator;
    PackageBundleAssembler assembler = new PackageBundleAssembler();

    /**
     * Return the `package` [Uri] for the given [path] in the `lib` folder
     * of the current package.
     */
    Uri getUri(String path) {
      String pathInLib = path.substring(libPath.length);
      String uriPath = pathos.posix.joinAll(pathContext.split(pathInLib));
      String uriStr = 'package:$packageName/$uriPath';
      return FastUri.parse(uriStr);
    }

    /**
     * If the given [file] is a Dart file, add its unlinked unit.
     */
    void addDartFile(File file) {
      String path = file.path;
      if (AnalysisEngine.isDartFileName(path)) {
        Uri uri = getUri(path);
        Source source = file.createSource(uri);
        CompilationUnit unit = _parse(source, strong);
        UnlinkedUnitBuilder unlinkedUnit = serializeAstUnlinked(unit);
        assembler.addUnlinkedUnit(source, unlinkedUnit);
      }
    }

    /**
     * Visit the [folder] recursively.
     */
    void addDartFiles(Folder folder) {
      List<Resource> children = folder.getChildren();
      for (Resource child in children) {
        if (child is File) {
          addDartFile(child);
        }
      }
      for (Resource child in children) {
        if (child is Folder) {
          addDartFiles(child);
        }
      }
    }

    addDartFiles(libFolder);
    return assembler.assemble();
  }

  /**
   * Parse the given [source] into AST.
   */
  static CompilationUnit _parse(Source source, bool strong) {
    String code = source.contents.data;
    AnalysisErrorListener errorListener = AnalysisErrorListener.NULL_LISTENER;
    CharSequenceReader reader = new CharSequenceReader(code);
    Scanner scanner = new Scanner(source, reader, errorListener);
    scanner.scanGenericMethodComments = strong;
    Token token = scanner.tokenize();
    LineInfo lineInfo = new LineInfo(scanner.lineStarts);
    Parser parser = new Parser(source, errorListener);
    parser.parseGenericMethodComments = strong;
    CompilationUnit unit = parser.parseCompilationUnit(token);
    unit.lineInfo = lineInfo;
    return unit;
  }
}

class _TestPackageResolver implements UriResolver {
  final ResourceProvider resourceProvider;
  final String sourceRoot;

  _TestPackageResolver(this.resourceProvider, this.sourceRoot);

  @override
  Source resolveAbsolute(Uri uri, [Uri actualUri]) {
    if (uri.scheme == 'package') {
      List<String> segments = uri.pathSegments;
      if (segments.isNotEmpty) {
        pathos.Context pathContext = resourceProvider.pathContext;
        String packageName = segments.first;
        String folderPath = pathContext.join(
            sourceRoot, packageName.replaceAll('.', pathContext.separator));
        String path = pathContext.join(
            folderPath, 'lib', pathContext.joinAll(segments.skip(1)));
        return resourceProvider.getFile(path).createSource(uri);
      }
    }
    return null;
  }

  @override
  Uri restoreAbsolute(Source source) {
    throw new UnimplementedError();
  }
}
