// Copyright (c) 2018, 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/file_system/file_system.dart';
import 'package:analyzer/file_system/memory_file_system.dart';
import 'package:analyzer/src/context/builder.dart';
import 'package:analyzer/src/generated/package_build.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:package_config/packages.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

main() {
  defineReflectiveSuite(() {
    defineReflectiveTests(PackageBuildFileUriResolverTest);
    defineReflectiveTests(PackageBuildPackageUriResolverTest);
    defineReflectiveTests(PackageBuildWorkspaceTest);
  });
}

class MockContextBuilder implements ContextBuilder {
  Map<String, Packages> packagesMapMap = <String, Packages>{};
  Map<Packages, Map<String, List<Folder>>> packagesToMapMap =
      <Packages, Map<String, List<Folder>>>{};

  Map<String, List<Folder>> convertPackagesToMap(Packages packages) =>
      packagesToMapMap[packages];

  Packages createPackageMap(String rootDirectoryPath) =>
      packagesMapMap[rootDirectoryPath];

  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}

class MockPackages implements Packages {
  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}

class MockUriResolver implements UriResolver {
  Map<Uri, Source> resolveAbsoluteMap = {};

  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);

  Source resolveAbsolute(Uri uri, [Uri actualUri]) => resolveAbsoluteMap[uri];
}

@reflectiveTest
class PackageBuildFileUriResolverTest extends _BaseTest {
  PackageBuildWorkspace workspace;
  PackageBuildFileUriResolver resolver;

  void setUp() {
    provider.newFolder(_p('/workspace/.dart_tool/build/generated/project/lib'));
    provider.newFileWithBytes(
        _p('/workspace/pubspec.yaml'), 'name: project'.codeUnits);
    final MockContextBuilder contextBuilder = new MockContextBuilder();
    final Packages packages = new MockPackages();
    contextBuilder.packagesMapMap[_p('/workspace')] = packages;
    contextBuilder.packagesToMapMap[packages] = {'project': []};
    workspace =
        PackageBuildWorkspace.find(provider, _p('/workspace'), contextBuilder);
    resolver = new PackageBuildFileUriResolver(workspace);
    provider.newFile(_p('/workspace/test.dart'), '');
    provider.newFile(
        _p('/workspace/.dart_tool/build/generated/project/gen.dart'), '');
  }

  void test_resolveAbsolute_doesNotExist() {
    Source source = _resolvePath('/workspace/foo.dart');
    expect(source, isNotNull);
    expect(source.exists(), isFalse);
    expect(source.fullName, _p('/workspace/foo.dart'));
  }

  void test_resolveAbsolute_file() {
    Source source = _resolvePath('/workspace/test.dart');
    expect(source, isNotNull);
    expect(source.exists(), isTrue);
    expect(source.fullName, _p('/workspace/test.dart'));
  }

  void test_resolveAbsolute_folder() {
    Source source = _resolvePath('/workspace');
    expect(source, isNotNull);
    expect(source.exists(), isFalse);
    expect(source.fullName, _p('/workspace'));
  }

  void test_resolveAbsolute_generated_file_exists_one() {
    Source source = _resolvePath('/workspace/gen.dart');
    expect(source, isNotNull);
    expect(source.exists(), isTrue);
    expect(source.fullName,
        _p('/workspace/.dart_tool/build/generated/project/gen.dart'));
  }

  void test_resolveAbsolute_notFile_dartUri() {
    Uri uri = new Uri(scheme: 'dart', path: 'core');
    Source source = resolver.resolveAbsolute(uri);
    expect(source, isNull);
  }

  void test_resolveAbsolute_notFile_httpsUri() {
    Uri uri = new Uri(scheme: 'https', path: '127.0.0.1/test.dart');
    Source source = resolver.resolveAbsolute(uri);
    expect(source, isNull);
  }

  void test_restoreAbsolute() {
    Uri uri = provider.pathContext.toUri(_p('/workspace/test.dart'));
    Source source = resolver.resolveAbsolute(uri);
    expect(source, isNotNull);
    expect(resolver.restoreAbsolute(source), uri);
    expect(
        resolver.restoreAbsolute(
            new NonExistingSource(source.fullName, null, null)),
        uri);
  }

  Source _resolvePath(String absolutePosixPath) {
    String absolutePath = provider.convertPath(absolutePosixPath);
    Uri uri = provider.pathContext.toUri(absolutePath);
    return resolver.resolveAbsolute(uri);
  }
}

@reflectiveTest
class PackageBuildPackageUriResolverTest extends _BaseTest {
  PackageBuildWorkspace workspace;
  PackageBuildPackageUriResolver resolver;
  MockUriResolver packageUriResolver;

  Uri addPackageSource(String path, String uriStr, {bool create: true}) {
    Uri uri = Uri.parse(uriStr);
    final File file = create
        ? provider.newFile(_p(path), '')
        : provider.getResource(_p(path));
    final Source source = file.createSource(uri);
    packageUriResolver.resolveAbsoluteMap[uri] = source;
    return uri;
  }

  void setUp() {
    provider.newFileWithBytes(
        _p('/workspace/pubspec.yaml'), 'name: project'.codeUnits);
  }

  void test_resolveAbsolute_generated() {
    _addResources([
      '/workspace/.dart_tool/build/generated/project/lib/generated_file.dart',
    ]);
    final Uri sourceUri = addPackageSource('/workspace/lib/generated_file.dart',
        'package:project/generated_file.dart',
        create: false);
    _assertResolveUri(sourceUri,
        '/workspace/.dart_tool/build/generated/project/lib/generated_file.dart',
        exists: true);
  }

  void test_resolveAbsolute_null_notPackage() {
    _addResources([
      '/workspace/.dart_tool/build/generated',
    ]);
    Source source = resolver.resolveAbsolute(Uri.parse('dart:async'));
    expect(source, isNull);
  }

  void test_resolveAbsolute_null_startsWithSlash() {
    _addResources([
      '/workspace/.dart_tool/build/generated',
    ]);
    Source source =
        resolver.resolveAbsolute(Uri.parse('package:/foo/bar.dart'));
    expect(source, isNull);
  }

  void test_resolveAbsolute_source() {
    _addResources([
      '/workspace/.dart_tool/build/generated/project/lib/source_file.dart',
    ]);
    final Uri sourceUri = addPackageSource(
        '/workspace/lib/source_file.dart', 'package:project/source_file.dart');
    _assertResolveUri(sourceUri, '/workspace/lib/source_file.dart',
        exists: true);
  }

  void test_resolveAbsolute_workspace_doesNotExist() {
    _addResources([
      '/workspace/.dart_tool/build/generated',
    ]);
    final Uri sourceUri = addPackageSource(
        '/workspace/lib/doesNotExist.dart', 'package:project/doesNotExist.dart',
        create: false);
    _assertResolveUri(sourceUri, '/workspace/lib/doesNotExist.dart',
        exists: false);
  }

  void _addResources(List<String> paths, {String workspacePath: '/workspace'}) {
    for (String path in paths) {
      if (path.endsWith('/')) {
        provider.newFolder(_p(path.substring(0, path.length - 1)));
      } else {
        provider.newFile(_p(path), '');
      }
    }
    final contextBuilder = new MockContextBuilder();
    final packages = new MockPackages();
    contextBuilder.packagesMapMap[_p(workspacePath)] = packages;
    contextBuilder.packagesToMapMap[packages] = {'project': []};
    workspace =
        PackageBuildWorkspace.find(provider, _p(workspacePath), contextBuilder);
    packageUriResolver = new MockUriResolver();
    resolver =
        new PackageBuildPackageUriResolver(workspace, packageUriResolver);
  }

  Source _assertResolveUri(Uri uri, String posixPath,
      {bool exists: true, bool restore: true}) {
    Source source = resolver.resolveAbsolute(uri);
    expect(source, isNotNull);
    expect(source.fullName, _p(posixPath));
    expect(source.uri, uri);
    expect(source.exists(), exists);
    // If enabled, test also "restoreAbsolute".
    if (restore) {
      Uri restoredUri = resolver.restoreAbsolute(source);
      expect(restoredUri.toString(), uri.toString());
    }
    return source;
  }
}

@reflectiveTest
class PackageBuildWorkspaceTest extends _BaseTest {
  void test_builtFile_currentProject() {
    provider.newFolder(_p('/workspace/.dart_tool/build'));
    provider.newFileWithBytes(
        _p('/workspace/pubspec.yaml'), 'name: project'.codeUnits);
    PackageBuildWorkspace workspace =
        _createWorkspace('/workspace', ['project']);

    final libFile = provider.newFile(
        _p('/workspace/.dart_tool/build/generated/project/lib/file.dart'), '');
    expect(workspace.builtFile(_p('lib/file.dart'), 'project'), libFile);
  }

  void test_builtFile_importedPackage() {
    provider.newFolder(_p('/workspace/.dart_tool/build'));
    provider.newFileWithBytes(
        _p('/workspace/pubspec.yaml'), 'name: project'.codeUnits);
    PackageBuildWorkspace workspace =
        _createWorkspace('/workspace', ['project', 'foo']);

    final libFile = provider.newFile(
        _p('/workspace/.dart_tool/build/generated/foo/lib/file.dart'), '');
    expect(workspace.builtFile(_p('lib/file.dart'), 'foo'), libFile);
  }

  void test_builtFile_notInPackagesGetsHidden() {
    provider.newFolder(_p('/workspace/.dart_tool/build'));
    provider.newFileWithBytes(
        _p('/workspace/pubspec.yaml'), 'name: project'.codeUnits);

    // Ensure package:bar is not configured.
    PackageBuildWorkspace workspace =
        _createWorkspace('/workspace', ['project', 'foo']);

    // Create a generated file in package:bar.
    provider.newFile(
        _p('/workspace/.dart_tool/build/generated/bar/lib/file.dart'), '');

    // Bar not in packages, file should not be returned.
    expect(workspace.builtFile('lib/file.dart', 'bar'), isNull);
  }

  void test_find_fail_notAbsolute() {
    expect(
        () => PackageBuildWorkspace.find(
            provider, _p('not_absolute'), new MockContextBuilder()),
        throwsArgumentError);
  }

  void test_find_hasDartToolAndPubspec() {
    provider.newFolder(_p('/workspace/.dart_tool/build/generated/project/lib'));
    provider.newFileWithBytes(
        _p('/workspace/pubspec.yaml'), 'name: project'.codeUnits);
    PackageBuildWorkspace workspace = PackageBuildWorkspace.find(
        provider, _p('/workspace'), new MockContextBuilder());
    expect(workspace.root, _p('/workspace'));
    expect(workspace.projectPackageName, 'project');
  }

  void test_find_hasDartToolAndPubspec_inParentDirectory() {
    provider.newFolder(_p('/workspace/.dart_tool/build/generated/project/lib'));
    provider.newFolder(_p('/workspace/opened/up/a/child/dir/.dart_tool/build'));
    provider.newFileWithBytes(
        _p('/workspace/opened/up/a/child/dir/pubspec.yaml'),
        'name: subproject'.codeUnits);
    provider.newFileWithBytes(
        _p('/workspace/pubspec.yaml'), 'name: project'.codeUnits);
    PackageBuildWorkspace workspace = PackageBuildWorkspace.find(provider,
        _p('/workspace/opened/up/a/child/dir'), new MockContextBuilder());
    expect(workspace.root, _p('/workspace/opened/up/a/child/dir'));
    expect(workspace.projectPackageName, 'subproject');
  }

  void
      test_find_hasDartToolAndPubspec_inParentDirectory_ignoresMalformedPubspec() {
    provider.newFolder(_p('/workspace/.dart_tool/build/generated/project/lib'));
    provider.newFolder(_p('/workspace/opened/up/a/child/dir/.dart_tool/build'));
    provider.newFileWithBytes(
        _p('/workspace/opened/up/a/child/dir/pubspec.yaml'),
        'not: yaml: here!!! 111'.codeUnits);
    provider.newFileWithBytes(
        _p('/workspace/pubspec.yaml'), 'name: project'.codeUnits);
    PackageBuildWorkspace workspace = PackageBuildWorkspace.find(provider,
        _p('/workspace/opened/up/a/child/dir'), new MockContextBuilder());
    expect(workspace.root, _p('/workspace'));
    expect(workspace.projectPackageName, 'project');
  }

  void test_find_hasDartToolAndPubspec_inParentDirectory_ignoresSoloDartTool() {
    provider.newFolder(_p('/workspace/.dart_tool/build/generated/project/lib'));
    provider.newFolder(_p('/workspace/opened/up/a/child/dir'));
    provider.newFolder(_p('/workspace/opened/up/a/child/dir/.dart_tool/build'));
    provider.newFileWithBytes(
        _p('/workspace/pubspec.yaml'), 'name: project'.codeUnits);
    PackageBuildWorkspace workspace = PackageBuildWorkspace.find(provider,
        _p('/workspace/opened/up/a/child/dir'), new MockContextBuilder());
    expect(workspace.root, _p('/workspace'));
    expect(workspace.projectPackageName, 'project');
  }

  void test_find_hasDartToolAndPubspec_inParentDirectory_ignoresSoloPubspec() {
    provider.newFolder(_p('/workspace/.dart_tool/build/generated/project/lib'));
    provider.newFolder(_p('/workspace/opened/up/a/child/dir'));
    provider.newFileWithBytes(
        _p('/workspace/opened/up/a/child/dir/pubspec.yaml'),
        'name: subproject'.codeUnits);
    provider.newFileWithBytes(
        _p('/workspace/pubspec.yaml'), 'name: project'.codeUnits);
    PackageBuildWorkspace workspace = PackageBuildWorkspace.find(provider,
        _p('/workspace/opened/up/a/child/dir'), new MockContextBuilder());
    expect(workspace.root, _p('/workspace'));
    expect(workspace.projectPackageName, 'project');
  }

  void test_find_hasDartToolNoBuild() {
    // Edge case: an empty .dart_tool directory. Don't assume package:build.
    provider.newFolder(_p('/workspace/.dart_tool'));
    provider.newFileWithBytes(
        _p('/workspace/pubspec.yaml'), 'name: project'.codeUnits);
    PackageBuildWorkspace workspace = PackageBuildWorkspace.find(
        provider, _p('/workspace'), new MockContextBuilder());
    expect(workspace, isNull);
  }

  void test_find_hasDartToolNoPubspec() {
    provider.newFolder(_p('/workspace/.dart_tool/build/generated/project/lib'));
    PackageBuildWorkspace workspace = PackageBuildWorkspace.find(
        provider, _p('/workspace'), new MockContextBuilder());
    expect(workspace, isNull);
  }

  void test_find_hasDartToolPubButNotBuild() {
    // Dart projects will have this directory, that don't use package:build.
    provider.newFolder(_p('/workspace/.dart_tool/pub'));
    provider.newFileWithBytes(
        _p('/workspace/pubspec.yaml'), 'name: project'.codeUnits);
    PackageBuildWorkspace workspace = PackageBuildWorkspace.find(
        provider, _p('/workspace'), new MockContextBuilder());
    expect(workspace, isNull);
  }

  void test_find_hasMalformedPubspec() {
    provider.newFolder(_p('/workspace/.dart_tool/build/generated/project/lib'));
    provider.newFileWithBytes(
        _p('/workspace/pubspec.yaml'), 'not: yaml: here! 1111'.codeUnits);
    PackageBuildWorkspace workspace = PackageBuildWorkspace.find(
        provider, _p('/workspace'), new MockContextBuilder());
    expect(workspace, isNull);
  }

  void test_find_hasPubspecNoDartTool() {
    provider.newFileWithBytes(
        _p('/workspace/pubspec.yaml'), 'name: project'.codeUnits);
    PackageBuildWorkspace workspace = PackageBuildWorkspace.find(
        provider, _p('/workspace'), new MockContextBuilder());
    expect(workspace, isNull);
  }

  void test_findFile_bin() {
    provider.newFolder(_p('/workspace/.dart_tool/build/generated/project/bin'));
    provider.newFileWithBytes(
        _p('/workspace/pubspec.yaml'), 'name: project'.codeUnits);
    PackageBuildWorkspace workspace =
        _createWorkspace('/workspace', ['project']);

    final binFile = provider.newFile(_p('/workspace/bin/file.dart'), '');
    expect(workspace.findFile(_p('/workspace/bin/file.dart')), binFile);
  }

  void test_findFile_binGenerated() {
    provider.newFolder(_p('/workspace/.dart_tool/build/generated/project/bin'));
    provider.newFileWithBytes(
        _p('/workspace/pubspec.yaml'), 'name: project'.codeUnits);
    PackageBuildWorkspace workspace =
        _createWorkspace('/workspace', ['project']);

    final binFile = provider.newFile(
        _p('/workspace/.dart_tool/build/generated/project/bin/file.dart'), '');
    expect(workspace.findFile(_p('/workspace/bin/file.dart')), binFile);
  }

  void test_findFile_libGenerated() {
    provider.newFolder(_p('/workspace/.dart_tool/build/generated/project/lib'));
    provider.newFileWithBytes(
        _p('/workspace/pubspec.yaml'), 'name: project'.codeUnits);
    PackageBuildWorkspace workspace =
        _createWorkspace('/workspace', ['project']);

    final libFile = provider.newFile(
        _p('/workspace/.dart_tool/build/generated/project/lib/file.dart'), '');
    expect(workspace.findFile(_p('/workspace/lib/file.dart')), libFile);
  }

  void test_findFile_test() {
    provider
        .newFolder(_p('/workspace/.dart_tool/build/generated/project/test'));
    provider.newFileWithBytes(
        _p('/workspace/pubspec.yaml'), 'name: project'.codeUnits);
    PackageBuildWorkspace workspace =
        _createWorkspace('/workspace', ['project']);

    final testFile = provider.newFile(_p('/workspace/test/file.dart'), '');
    expect(workspace.findFile(_p('/workspace/test/file.dart')), testFile);
  }

  void test_findFile_testGenerated() {
    provider
        .newFolder(_p('/workspace/.dart_tool/build/generated/project/test'));
    provider.newFileWithBytes(
        _p('/workspace/pubspec.yaml'), 'name: project'.codeUnits);
    PackageBuildWorkspace workspace =
        _createWorkspace('/workspace', ['project']);

    final testFile = provider.newFile(
        _p('/workspace/.dart_tool/build/generated/project/test/file.dart'), '');
    expect(workspace.findFile(_p('/workspace/test/file.dart')), testFile);
  }

  void test_findFile_web() {
    provider.newFolder(_p('/workspace/.dart_tool/build/generated/project/web'));
    provider.newFileWithBytes(
        _p('/workspace/pubspec.yaml'), 'name: project'.codeUnits);
    PackageBuildWorkspace workspace =
        _createWorkspace('/workspace', ['project']);

    final webFile = provider.newFile(_p('/workspace/web/file.dart'), '');
    expect(workspace.findFile(_p('/workspace/web/file.dart')), webFile);
  }

  void test_findFile_webGenerated() {
    provider.newFolder(_p('/workspace/.dart_tool/build/generated/project/web'));
    provider.newFileWithBytes(
        _p('/workspace/pubspec.yaml'), 'name: project'.codeUnits);
    PackageBuildWorkspace workspace =
        _createWorkspace('/workspace', ['project']);

    final webFile = provider.newFile(
        _p('/workspace/.dart_tool/build/generated/project/web/file.dart'), '');
    expect(workspace.findFile(_p('/workspace/web/file.dart')), webFile);
  }

  PackageBuildWorkspace _createWorkspace(
      String root, List<String> packageNames) {
    final contextBuilder = new MockContextBuilder();
    final packages = new MockPackages();
    final packageMap = new Map.fromIterable(packageNames, value: ((_) => []));
    contextBuilder.packagesMapMap[_p(root)] = packages;
    contextBuilder.packagesToMapMap[packages] = packageMap;
    return PackageBuildWorkspace.find(provider, _p(root), contextBuilder);
  }
}

class _BaseTest {
  final MemoryResourceProvider provider = new MemoryResourceProvider();

  /**
   * Return the [provider] specific path for the given Posix [path].
   */
  String _p(String path) => provider.convertPath(path);
}
