// Copyright 2014 The Flutter Authors. 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:io';

import 'package:args/args.dart';
import 'package:file/local.dart';
import 'package:glob/glob.dart';
import 'package:path/path.dart' as path;

import 'lib/runner.dart';

Future<void> main(List<String> arguments) async {
  exit(await run(arguments) ? 0 : 1);
}

// Return true if successful, false if failed.
Future<bool> run(List<String> arguments) async {
  final argParser = ArgParser(allowTrailingOptions: false, usageLineLength: 72)
    ..addOption(
      'repeat',
      defaultsTo: '1',
      help:
          'How many times to run each test. Set to a high value to look for flakes. If a test specifies a number of iterations, the lower of the two values is used.',
      valueHelp: 'count',
    )
    ..addOption(
      'shards',
      defaultsTo: '1',
      help: 'How many shards to split the tests into. Used in continuous integration.',
      valueHelp: 'count',
    )
    ..addOption(
      'shard-index',
      defaultsTo: '0',
      help:
          'The current shard to run the tests with the range [0 .. shards - 1]. Used in continuous integration.',
      valueHelp: 'count',
    )
    ..addFlag('skip-on-fetch-failure', help: 'Whether to skip tests that we fail to download.')
    ..addFlag('skip-template', help: 'Whether to skip tests named "template.test".')
    ..addFlag('verbose', help: 'Describe what is happening in detail.')
    ..addFlag('help', negatable: false, help: 'Print this help message.');

  void printHelp() {
    print('run_tests.dart [options...] path/to/file1.test path/to/file2.test...');
    print('For details on the test registry format, see:');
    print('  https://github.com/flutter/tests/blob/main/registry/template.test');
    print('');
    print(argParser.usage);
    print('');
  }

  ArgResults parsedArguments;
  try {
    parsedArguments = argParser.parse(arguments);
  } on ArgParserException catch (error) {
    printHelp();
    print('Error: ${error.message} Use --help for usage information.');
    exit(1);
  }

  final int? repeat = int.tryParse(parsedArguments['repeat'] as String);
  final skipOnFetchFailure = parsedArguments['skip-on-fetch-failure'] as bool;
  final skipTemplate = parsedArguments['skip-template'] as bool;
  final verbose = parsedArguments['verbose'] as bool;
  final help = parsedArguments['help'] as bool;
  final int? numberShards = int.tryParse(parsedArguments['shards'] as String);
  final int? shardIndex = int.tryParse(parsedArguments['shard-index'] as String);
  final List<File> files = parsedArguments.rest
      .expand((String path) => Glob(path).listFileSystemSync(const LocalFileSystem()))
      .whereType<File>()
      .where((File file) => !skipTemplate || path.basename(file.path) != 'template.test')
      .toList();

  if (files.isEmpty && parsedArguments.rest.isNotEmpty) {
    print('No files resolved from glob(s): ${parsedArguments.rest}');
  }

  if (help ||
      repeat == null ||
      files.isEmpty ||
      numberShards == null ||
      numberShards <= 0 ||
      shardIndex == null ||
      shardIndex < 0) {
    printHelp();
    if (verbose) {
      if (repeat == null) {
        print('Error: Could not parse repeat count ("${parsedArguments['repeat']}")');
      }
      if (numberShards == null) {
        print('Error: Could not parse shards count ("${parsedArguments['shards']}")');
      } else if (numberShards < 1) {
        print(
          'Error: The specified shards count ($numberShards) is less than 1. It must be greater than zero.',
        );
      }
      if (shardIndex == null) {
        print('Error: Could not parse shard index ("${parsedArguments['shard-index']}")');
      } else if (shardIndex < 0) {
        print(
          'Error: The specified shard index ($shardIndex) is negative. It must be in the range [0 .. shards - 1].',
        );
      }
      if (parsedArguments.rest.isEmpty) {
        print('Error: No file arguments specified.');
      } else if (files.isEmpty) {
        print(
          'Error: File arguments ("${parsedArguments.rest.join('", "')}") did not identify any real files.',
        );
      }
    }
    return help;
  }

  if (shardIndex > numberShards - 1) {
    print(
      'Error: The specified shard index ($shardIndex) is more than the specified number of shards ($numberShards). '
      'It must be in the range [0 .. shards - 1].',
    );
    return false;
  }

  if (files.length < numberShards) {
    print('Warning: There are more shards than tests. Some shards will not run any tests.');
  }

  return runTests(
    repeat: repeat,
    skipOnFetchFailure: skipOnFetchFailure,
    verbose: verbose,
    numberShards: numberShards,
    shardIndex: shardIndex,
    files: files,
  );
}
