// 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 BenchmarkingBinding binding = BenchmarkingBinding();
  final List<Benchmark> 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 ArgParser 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 List<String> mainArgs = <String>[];
  const String testArgs = String.fromEnvironment('tests');
  if (testArgs.isNotEmpty) {
    mainArgs.addAll(<String>['--tests', testArgs]);
    print('╡ ••• environment test override: $testArgs ••• ╞');
  }
  const String 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 becauase we don't want order dependent tests.
  // It is the responsibily 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 Benchmark 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');
  exit(0);
}
