// Copyright (c) 2020, 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.

// @dart=2.10

import 'dart:io';

import 'package:path/path.dart' show separator;
import 'package:path/path.dart' as p;
import 'package:pub/pub.dart';
import 'package:test/test.dart';

import '../descriptor.dart' as d;
import '../test_pub.dart';

Future<void> testGetExecutable(String command, String root,
    {allowSnapshot = true, result, errorMessage}) async {
  final _cachePath = getPubTestEnvironment()['PUB_CACHE'];
  if (result == null) {
    expect(
      () => getExecutableForCommand(
        command,
        root: root,
        pubCacheDir: _cachePath,
        allowSnapshot: allowSnapshot,
      ),
      throwsA(
        isA<CommandResolutionFailedException>()
            .having((e) => e.message, 'message', errorMessage),
      ),
    );
  } else {
    final path = await getExecutableForCommand(
      command,
      root: root,
      pubCacheDir: _cachePath,
      allowSnapshot: allowSnapshot,
    );
    expect(path, result);
    expect(File(p.join(root, path)).existsSync(), true);
  }
}

Future<void> main() async {
  test('Finds a direct dart-file without pub get', () async {
    await d.dir('foo', [
      d.dir('bar', [d.file('bar.dart', 'main() {print(42);}')])
    ]).create();
    final dir = d.path('foo');

    await testGetExecutable('bar/bar.dart', dir,
        result: p.join('bar', 'bar.dart'));

    await testGetExecutable(p.join('bar', 'bar.dart'), dir,
        result: p.join('bar', 'bar.dart'));

    await testGetExecutable('${p.toUri(dir)}/bar/bar.dart', dir,
        result: p.join('bar', 'bar.dart'));
  });

  test('Looks for file when no pubspec.yaml', () async {
    await d.dir('foo', [
      d.dir('bar', [d.file('bar.dart', 'main() {print(42);}')])
    ]).create();
    final dir = d.path('foo');

    await testGetExecutable('bar/m.dart', dir,
        errorMessage: contains('Could not find file `bar/m.dart`'));
    await testGetExecutable(p.join('bar', 'm.dart'), dir,
        errorMessage: contains('Could not find file `bar${separator}m.dart`'));
  });

  test('Error message when pubspec is broken', () async {
    await d.dir('foo', [
      d.pubspec({
        'name': 'broken name',
      }),
    ]).create();

    await d.dir(appPath, [
      d.pubspec({
        'name': 'myapp',
        'environment': {'sdk': '>=$_currentVersion <3.0.0'},
        'dependencies': {
          'foo': {
            'path': '../foo',
          },
        },
      }),
    ]).create();
    final dir = d.path(appPath);
    await testGetExecutable('foo:app', dir,
        errorMessage: allOf(
            contains(
                'Error on line 1, column 9 of ${d.sandbox}${p.separator}foo${p.separator}pubspec.yaml: "name" field must be a valid Dart identifier.'),
            contains(
                '{"name":"broken name","environment":{"sdk":">=0.1.2 <1.0.0"}}')));
  });

  test('Does `pub get` if there is a pubspec.yaml', () async {
    await d.dir(appPath, [
      d.pubspec({
        'name': 'myapp',
        'dependencies': {'foo': '^1.0.0'}
      }),
      d.dir('bin', [
        d.file('myapp.dart', 'main() {print(42);}'),
      ])
    ]).create();

    await serveNoPackages();
    // The solver uses word-wrapping in its error message, so we use \s to
    // accomodate.
    await testGetExecutable('bar/m.dart', d.path(appPath),
        errorMessage: matches(r'version\s+solving\s+failed'));
  });

  test('Finds files', () async {
    await servePackages((b) => b
      ..serve('foo', '1.0.0', pubspec: {
        'environment': {'sdk': '>=$_currentVersion <3.0.0'}
      }, contents: [
        d.dir('bin', [
          d.file('foo.dart', 'main() {print(42);}'),
          d.file('tool.dart', 'main() {print(42);}')
        ])
      ]));

    await d.dir(appPath, [
      d.pubspec({
        'name': 'myapp',
        'environment': {'sdk': '>=2.0.0 <3.0.0'},
        'dependencies': {
          'foo': {
            'hosted': {
              'name': 'foo',
              'url': getPubTestEnvironment()['PUB_HOSTED_URL'],
            },
            'version': '^1.0.0',
          },
        },
      }),
      d.dir('bin', [
        d.file('myapp.dart', 'main() {print(42);}'),
        d.file('tool.dart', 'main() {print(42);}')
      ])
    ]).create();
    final dir = d.path(appPath);

    await testGetExecutable('myapp', dir,
        result: p.join('.dart_tool', 'pub', 'bin', 'myapp',
            'myapp.dart-$_currentVersion.snapshot'));
    await testGetExecutable('myapp:myapp', dir,
        result: p.join('.dart_tool', 'pub', 'bin', 'myapp',
            'myapp.dart-$_currentVersion.snapshot'));
    await testGetExecutable(':myapp', dir,
        result: p.join('.dart_tool', 'pub', 'bin', 'myapp',
            'myapp.dart-$_currentVersion.snapshot'));
    await testGetExecutable(':tool', dir,
        result: p.join('.dart_tool', 'pub', 'bin', 'myapp',
            'tool.dart-$_currentVersion.snapshot'));
    await testGetExecutable('foo', dir,
        allowSnapshot: false,
        result: endsWith('foo-1.0.0${separator}bin${separator}foo.dart'));
    await testGetExecutable('foo', dir,
        result:
            '.dart_tool${separator}pub${separator}bin${separator}foo${separator}foo.dart-$_currentVersion.snapshot');
    await testGetExecutable('foo:tool', dir,
        allowSnapshot: false,
        result: endsWith('foo-1.0.0${separator}bin${separator}tool.dart'));
    await testGetExecutable('foo:tool', dir,
        result:
            '.dart_tool${separator}pub${separator}bin${separator}foo${separator}tool.dart-$_currentVersion.snapshot');
    await testGetExecutable(
      'unknown:tool',
      dir,
      errorMessage: 'Could not find package `unknown` or file `unknown:tool`',
    );
    await testGetExecutable(
      'foo:unknown',
      dir,
      errorMessage:
          'Could not find `bin${separator}unknown.dart` in package `foo`.',
    );
    await testGetExecutable(
      'unknownTool',
      dir,
      errorMessage:
          'Could not find package `unknownTool` or file `unknownTool`',
    );
  });
}

final _currentVersion = Platform.version.split(' ').first;
