// Copyright (c) 2015, 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:convert';

import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/file_system/memory_file_system.dart';
import 'package:analyzer/src/file_system/file_system.dart';
import 'package:analyzer/src/generated/engine.dart' show AnalysisEngine, Logger;
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/source_io.dart';
import 'package:analyzer/src/generated/utilities_dart.dart' as utils;
import 'package:analyzer/src/source/package_map_resolver.dart';
import 'package:analyzer/src/source/source_resource.dart';
import 'package:package_config/packages.dart';
import 'package:package_config/packages_file.dart' as pkgfile show parse;
import 'package:package_config/src/packages_impl.dart';
import 'package:path/path.dart' as pathos;
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

import 'test_support.dart';

main() {
  runPackageMapTests();
  defineReflectiveSuite(() {
    defineReflectiveTests(SourceFactoryTest);
  });
}

Source createSource({String path, String uri}) =>
    //TODO(pquitslund): find some way to pass an actual URI into source creation
    new MemoryResourceProvider()
        .getFile(path)
        .createSource(uri != null ? Uri.parse(uri) : null);

void runPackageMapTests() {
  MemoryResourceProvider resourceProvider = new MemoryResourceProvider();
  final Uri baseUri = new Uri.file('test/base');
  final List<UriResolver> testResolvers = [
    new ResourceUriResolver(resourceProvider)
  ];

  Packages createPackageMap(Uri base, String configFileContents) {
    List<int> bytes = utf8.encode(configFileContents);
    Map<String, Uri> map = pkgfile.parse(bytes, base);
    return new MapPackages(map);
  }

  Map<String, List<Folder>> getPackageMap(String config) {
    Packages packages = createPackageMap(baseUri, config);
    SourceFactory factory = new SourceFactory(testResolvers, packages);
    return factory.packageMap;
  }

  String resolvePackageUri(
      {String uri,
      String config,
      Source containingSource,
      UriResolver customResolver}) {
    Packages packages = createPackageMap(baseUri, config);
    List<UriResolver> resolvers = testResolvers.toList();
    if (customResolver != null) {
      resolvers.add(customResolver);
    }
    SourceFactory factory = new SourceFactory(resolvers, packages);

    expect(AnalysisEngine.instance.logger, Logger.NULL);
    var logger = new TestLogger();
    AnalysisEngine.instance.logger = logger;
    try {
      Source source = factory.resolveUri(containingSource, uri);
      expect(logger.log, []);
      return source != null ? source.fullName : null;
    } finally {
      AnalysisEngine.instance.logger = Logger.NULL;
    }
  }

  Uri restorePackageUri(
      {Source source, String config, UriResolver customResolver}) {
    Packages packages = createPackageMap(baseUri, config);
    List<UriResolver> resolvers = testResolvers.toList();
    if (customResolver != null) {
      resolvers.add(customResolver);
    }
    SourceFactory factory = new SourceFactory(resolvers, packages);
    return factory.restoreUri(source);
  }

  String _p(String path) => resourceProvider.convertPath(path);

  Uri _u(String path) => resourceProvider.pathContext.toUri(_p(path));

  group('SourceFactoryTest', () {
    group('package mapping', () {
      group('resolveUri', () {
        test('URI in mapping', () {
          String uri = resolvePackageUri(config: '''
unittest:${_u('/home/somebody/.pub/cache/unittest-0.9.9/lib/')}
async:${_u('/home/somebody/.pub/cache/async-1.1.0/lib/')}
quiver:${_u('/home/somebody/.pub/cache/quiver-1.2.1/lib')}
''', uri: 'package:unittest/unittest.dart');
          expect(
              uri,
              equals(_p(
                  '/home/somebody/.pub/cache/unittest-0.9.9/lib/unittest.dart')));
        });
        test('URI not in mapping', () {
          String uri = resolvePackageUri(config: '''
unittest:${_u('/home/somebody/.pub/cache/unittest-0.9.9/lib/')}
async:${_u('/home/somebody/.pub/cache/async-1.1.0/lib/')}
quiver:${_u('/home/somebody/.pub/cache/quiver-1.2.1/lib')}
''', uri: 'package:foo/foo.dart');
          expect(uri, isNull);
        });
        test('Non-package URI', () {
          var testResolver = new CustomUriResolver(uriPath: _p('/test.dart'));
          String uri = resolvePackageUri(config: '''
unittest:${_u('/home/somebody/.pub/cache/unittest-0.9.9/lib/')}
''', uri: 'custom:custom.dart', customResolver: testResolver);
          expect(uri, testResolver.uriPath);
        });
        test('Bad package URI', () {
          String uri = resolvePackageUri(config: '', uri: 'package:foo');
          expect(uri, isNull);
        });
        test('Invalid URI', () {
          // TODO(pquitslund): fix clients to handle errors appropriately
          //   CLI: print message 'invalid package file format'
          //   SERVER: best case tell user somehow and recover...
          expect(
              () => resolvePackageUri(
                  config: 'foo:<:&%>', uri: 'package:foo/bar.dart'),
              throwsA(new TypeMatcher<FormatException>()));
        });
        test('Valid URI that cannot be further resolved', () {
          String uri = resolvePackageUri(
              config: 'foo:http://www.google.com', uri: 'package:foo/bar.dart');
          expect(uri, isNull);
        });
        test('Relative URIs', () {
          Source containingSource = createSource(
              path: _p('/foo/bar/baz/foo.dart'), uri: 'package:foo/foo.dart');
          String uri = resolvePackageUri(
              config: 'foo:${_u('/foo/bar/baz')}',
              uri: 'bar.dart',
              containingSource: containingSource);
          expect(uri, isNotNull);
          expect(uri, equals(_p('/foo/bar/baz/bar.dart')));
        });
      });
      group('restoreUri', () {
        test('URI in mapping', () {
          Uri uri = restorePackageUri(
              config: '''
unittest:${_u('/home/somebody/.pub/cache/unittest-0.9.9/lib/')}
async:${_u('/home/somebody/.pub/cache/async-1.1.0/lib/')}
quiver:${_u('/home/somebody/.pub/cache/quiver-1.2.1/lib')}
''',
              source: new FileSource(resourceProvider.getFile(_p(
                  '/home/somebody/.pub/cache/unittest-0.9.9/lib/unittest.dart'))));
          expect(uri, isNotNull);
          expect(uri.toString(), equals('package:unittest/unittest.dart'));
        });
      });
      group('packageMap', () {
        test('non-file URIs filtered', () {
          Map<String, List<Folder>> map = getPackageMap('''
quiver:${_u('/home/somebody/.pub/cache/quiver-1.2.1/lib')}
foo:http://www.google.com
''');
          expect(map.keys, unorderedEquals(['quiver']));
        });
      });
    });
  });

  group('URI utils', () {
    group('URI', () {
      test('startsWith', () {
        expect(utils.startsWith(Uri.parse('/foo/bar/'), Uri.parse('/foo/')),
            isTrue);
        expect(utils.startsWith(Uri.parse('/foo/bar/'), Uri.parse('/foo/bar/')),
            isTrue);
        expect(utils.startsWith(Uri.parse('/foo/bar'), Uri.parse('/foo/b')),
            isFalse);
        // Handle odd URIs (https://github.com/dart-lang/sdk/issues/24126)
        expect(utils.startsWith(Uri.parse('/foo/bar'), Uri.parse('')), isFalse);
        expect(utils.startsWith(Uri.parse(''), Uri.parse('/foo/bar')), isFalse);
      });
    });
  });
}

class AbsoluteUriResolver extends UriResolver {
  final MemoryResourceProvider resourceProvider;

  AbsoluteUriResolver(this.resourceProvider);

  @override
  Source resolveAbsolute(Uri uri, [Uri actualUri]) {
    return new FileSource(
        resourceProvider.getFile(resourceProvider.pathContext.fromUri(uri)),
        actualUri);
  }
}

class CustomUriResolver extends UriResolver {
  String uriPath;
  CustomUriResolver({this.uriPath});

  @override
  Source resolveAbsolute(Uri uri, [Uri actualUri]) =>
      createSource(path: uriPath);
}

@reflectiveTest
class SourceFactoryTest {
  MemoryResourceProvider resourceProvider = new MemoryResourceProvider();

  void test_creation() {
    expect(new SourceFactory([]), isNotNull);
  }

  void test_fromEncoding_invalidUri() {
    SourceFactory factory = new SourceFactory([]);
    expect(() => factory.fromEncoding("<:&%>"), throwsArgumentError);
  }

  void test_fromEncoding_noResolver() {
    SourceFactory factory = new SourceFactory([]);
    expect(() => factory.fromEncoding("foo:/does/not/exist.dart"),
        throwsArgumentError);
  }

  void test_fromEncoding_valid() {
    String encoding = "file:///does/not/exist.dart";
    SourceFactory factory = new SourceFactory(
        [new UriResolver_SourceFactoryTest_test_fromEncoding_valid(encoding)]);
    expect(factory.fromEncoding(encoding), isNotNull);
  }

  void test_resolveUri_absolute() {
    UriResolver_absolute resolver = new UriResolver_absolute();
    SourceFactory factory = new SourceFactory([resolver]);
    factory.resolveUri(null, "dart:core");
    expect(resolver.invoked, isTrue);
  }

  void test_resolveUri_nonAbsolute_absolute() {
    SourceFactory factory =
        new SourceFactory([new AbsoluteUriResolver(resourceProvider)]);
    String sourcePath = resourceProvider.convertPath('/does/not/exist.dart');
    String targetRawPath = '/does/not/matter.dart';
    String targetPath = resourceProvider.convertPath(targetRawPath);
    String targetUri =
        resourceProvider.pathContext.toUri(targetRawPath).toString();
    Source sourceSource = new FileSource(resourceProvider.getFile(sourcePath));
    Source result = factory.resolveUri(sourceSource, targetUri);
    expect(result.fullName, targetPath);
  }

  void test_resolveUri_nonAbsolute_relative() {
    SourceFactory factory =
        new SourceFactory([new AbsoluteUriResolver(resourceProvider)]);
    String path = _p('/does/not/have.dart');
    Source containingSource = new FileSource(resourceProvider.getFile(path));
    Source result = factory.resolveUri(containingSource, 'exist.dart');
    expect(result.fullName, _p('/does/not/exist.dart'));
  }

  void test_resolveUri_nonAbsolute_relative_package() {
    MemoryResourceProvider provider = new MemoryResourceProvider();
    pathos.Context context = provider.pathContext;
    String packagePath =
        context.joinAll([context.separator, 'path', 'to', 'package']);
    String libPath = context.joinAll([packagePath, 'lib']);
    String dirPath = context.joinAll([libPath, 'dir']);
    String firstPath = context.joinAll([dirPath, 'first.dart']);
    String secondPath = context.joinAll([dirPath, 'second.dart']);

    provider.newFolder(packagePath);
    Folder libFolder = provider.newFolder(libPath);
    provider.newFolder(dirPath);
    File firstFile = provider.newFile(firstPath, '');
    provider.newFile(secondPath, '');

    PackageMapUriResolver resolver = new PackageMapUriResolver(provider, {
      'package': [libFolder]
    });
    SourceFactory factory = new SourceFactory([resolver]);
    Source librarySource =
        firstFile.createSource(Uri.parse('package:package/dir/first.dart'));

    Source result = factory.resolveUri(librarySource, 'second.dart');
    expect(result, isNotNull);
    expect(result.fullName, secondPath);
    expect(result.uri.toString(), 'package:package/dir/second.dart');
  }

  void test_restoreUri() {
    File file1 = resourceProvider.getFile(_p("/some/file1.dart"));
    File file2 = resourceProvider.getFile(_p("/some/file2.dart"));
    Source source1 = new FileSource(file1);
    Source source2 = new FileSource(file2);
    Uri expected1 = Uri.parse("file:///my_file.dart");
    SourceFactory factory =
        new SourceFactory([new UriResolver_restoreUri(source1, expected1)]);
    expect(factory.restoreUri(source1), same(expected1));
    expect(factory.restoreUri(source2), same(null));
  }

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

class UriResolver_absolute extends UriResolver {
  bool invoked = false;

  UriResolver_absolute();

  @override
  Source resolveAbsolute(Uri uri, [Uri actualUri]) {
    invoked = true;
    return null;
  }
}

class UriResolver_restoreUri extends UriResolver {
  Source source1;
  Uri expected1;
  UriResolver_restoreUri(this.source1, this.expected1);

  @override
  Source resolveAbsolute(Uri uri, [Uri actualUri]) => null;

  @override
  Uri restoreAbsolute(Source source) {
    if (identical(source, source1)) {
      return expected1;
    }
    return null;
  }
}

class UriResolver_SourceFactoryTest_test_fromEncoding_valid
    extends UriResolver {
  String encoding;
  UriResolver_SourceFactoryTest_test_fromEncoding_valid(this.encoding);

  @override
  Source resolveAbsolute(Uri uri, [Uri actualUri]) {
    if (uri.toString() == encoding) {
      return new TestSource();
    }
    return null;
  }
}
