// 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 'dart:math';

import 'package:args/args.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter_test/flutter_test.dart';

import 'benchmark_binding.dart';
import 'foundation/all_elements_bench.dart' as all_elements_bench;
import 'foundation/change_notifier_bench.dart' as change_notifier_bench;
import 'foundation/clamp.dart' as clamp;
import 'foundation/decode_and_parse_asset_manifest.dart' as decode_and_parse_asset_manifest;
import 'foundation/observer_list_bench.dart' as observer_list_bench;
import 'foundation/platform_asset_bundle.dart' as platform_asset_bundle;
import 'foundation/standard_message_codec_bench.dart' as standard_message_codec_bench;
import 'foundation/standard_method_codec_bench.dart' as standard_method_codec_bench;
import 'foundation/timeline_bench.dart' as timeline_bench;
import 'geometry/matrix_utils_transform_bench.dart' as matrix_utils_transform_bench;
import 'geometry/rrect_contains_bench.dart' as rrect_contains_bench;
import 'gestures/gesture_detector_bench.dart' as gesture_detector_bench;
import 'gestures/velocity_tracker_bench.dart' as velocity_tracker_bench;
import 'language/compute_bench.dart' as compute_bench;
import 'language/sync_star_bench.dart' as sync_star_bench;
import 'language/sync_star_semantics_bench.dart' as sync_star_semantics_bench;
import 'layout/text_intrinsic_bench.dart' as text_intrinsic_bench;
import 'stocks/animation_bench.dart' as animation_bench;
import 'stocks/build_bench.dart' as build_bench;
import 'stocks/build_bench_profiled.dart' as build_bench_profiled;
import 'stocks/layout_bench.dart' as layout_bench;
import 'ui/image_bench.dart' as image_bench;

typedef Benchmark = (String name, Future<void> Function() value);

Future<void> main() async {
  assert(false, "Don't run benchmarks in debug mode! Use 'flutter run --release'.");

  // BenchmarkingBinding is used by animation_bench, providing a simple
  // stopwatch interface over rendering. Lifting it here makes all
  // benchmarks run together.
  final binding = BenchmarkingBinding();
  final benchmarks = <Benchmark>[
    ('foundation/change_notifier_bench.dart', change_notifier_bench.execute),
    ('foundation/clamp.dart', clamp.execute),
    ('foundation/platform_asset_bundle.dart', platform_asset_bundle.execute),
    ('foundation/standard_message_codec_bench.dart', standard_message_codec_bench.execute),
    ('foundation/standard_method_codec_bench.dart', standard_method_codec_bench.execute),
    ('foundation/timeline_bench.dart', timeline_bench.execute),
    ('foundation/decode_and_parse_asset_manifest.dart', decode_and_parse_asset_manifest.execute),
    ('foundation/observer_list_bench.dart', observer_list_bench.execute),
    ('geometry/matrix_utils_transform_bench.dart', matrix_utils_transform_bench.execute),
    ('geometry/rrect_contains_bench.dart', rrect_contains_bench.execute),
    ('gestures/gesture_detector_bench.dart', gesture_detector_bench.execute),
    ('gestures/velocity_tracker_bench.dart', velocity_tracker_bench.execute),
    ('language/compute_bench.dart', compute_bench.execute),
    ('language/sync_star_bench.dart', sync_star_bench.execute),
    ('language/sync_star_semantics_bench.dart', sync_star_semantics_bench.execute),
    ('stocks/animation_bench.dart', () => animation_bench.execute(binding)),
    ('stocks/build_bench.dart', build_bench.execute),
    ('stocks/build_bench_profiled.dart', build_bench_profiled.execute),
    ('stocks/layout_bench.dart', layout_bench.execute),
    ('ui/image_bench.dart', image_bench.execute),
    ('layout/text_intrinsic_bench.dart', text_intrinsic_bench.execute),
    (
      'foundation/all_elements_bench.dart',
      () async {
        binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.benchmarkLive;
        runApp(const SizedBox.shrink()); // ensure dispose
        await SchedulerBinding.instance.endOfFrame;
        await all_elements_bench.execute();
      },
    ),
  ];

  // Parses the optional compile-time dart variables; we can't have
  // arguments passed in to main.
  final parser = ArgParser();
  final List<String> allowed = benchmarks.map((Benchmark e) => e.$1).toList();
  parser.addMultiOption(
    'tests',
    abbr: 't',
    defaultsTo: allowed,
    allowed: allowed,
    help: 'selected tests to run',
  );
  parser.addOption('seed', defaultsTo: '12345', help: 'selects seed to sort tests by');
  final mainArgs = <String>[];
  const testArgs = String.fromEnvironment('tests');
  if (testArgs.isNotEmpty) {
    mainArgs.addAll(<String>['--tests', testArgs]);
    print('╡ ••• environment test override: $testArgs ••• ╞');
  }
  const seedArgs = String.fromEnvironment('seed');
  if (seedArgs.isNotEmpty) {
    mainArgs.addAll(<String>['--seed', seedArgs]);
    print('╡ ••• environment seed override: $seedArgs ••• ╞');
  }
  final ArgResults results = parser.parse(mainArgs);
  final List<String> selectedTests = results.multiOption('tests');

  // Shuffle the tests because we don't want order dependent tests.
  // It is the responsibility of the infra to tell us what the seed value is,
  // in case we want to have the seed stable for some time period.
  final List<Benchmark> tests = benchmarks
      .where((Benchmark e) => selectedTests.contains(e.$1))
      .toList();
  tests.shuffle(Random(int.parse(results.option('seed')!)));

  print('╡ ••• Running microbenchmarks ••• ╞');
  for (final mark in tests) {
    // Reset the frame policy to default - each test can set it on their own.
    binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fadePointers;
    print('╡ ••• Running ${mark.$1} ••• ╞');
    await mark.$2();
  }

  print('\n\n╡ ••• Done ••• ╞\n\n');

  // Ensure stdout buffers are flushed so the collecting process gets Done
  await stdout.flush();

  // Now we're just being paranoid here and letting the process churn through
  // log lines before handling the exit code.
  await Future<void>.delayed(const Duration(seconds: 5));
  exit(0);
}
