// 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.
//
// Benchmark for runtimeType patterns as used in Flutter.

// ignore_for_file: prefer_const_constructors
// ignore_for_file: avoid_function_literals_in_foreach_calls

import 'dart:typed_data';

import 'package:benchmark_harness/benchmark_harness.dart';

abstract class Key {
  const factory Key(String value) = ValueKey<String>;
  const Key.empty();
}

abstract class LocalKey extends Key {
  const LocalKey() : super.empty();
}

class ValueKey<T> extends LocalKey {
  const ValueKey(this.value);
  final T value;
  @override
  bool operator ==(Object other) {
    if (other.runtimeType != runtimeType) return false;
    return other is ValueKey<T> && other.value == value;
  }

  @override
  int get hashCode => value.hashCode;
}

abstract class Widget {
  const Widget({this.key});
  final Key? key;

  @pragma('dart2js:noInline')
  static bool canUpdate(Widget oldWidget, Widget newWidget) {
    return oldWidget.runtimeType == newWidget.runtimeType &&
        oldWidget.key == newWidget.key;
  }
}

class AWidget extends Widget {
  const AWidget({Key? key}) : super(key: key);
}

class BWidget extends Widget {
  const BWidget({Key? key}) : super(key: key);
}

class CWidget extends Widget {
  const CWidget({Key? key}) : super(key: key);
}

class DWidget extends Widget {
  const DWidget({Key? key}) : super(key: key);
}

class EWidget extends Widget {
  const EWidget({Key? key}) : super(key: key);
}

class FWidget extends Widget {
  const FWidget({Key? key}) : super(key: key);
}

class WWidget<W extends Widget> extends Widget {
  final W? ref;
  const WWidget({this.ref, Key? key}) : super(key: key);
}

class WidgetCanUpdateBenchmark extends BenchmarkBase {
  WidgetCanUpdateBenchmark() : super('RuntimeType.Widget.canUpdate.byType');

  // All widgets have different types.
  static List<Widget> _widgets() => [
        AWidget(),
        BWidget(),
        CWidget(),
        DWidget(),
        EWidget(),
        FWidget(),
        WWidget<AWidget>(),
        WWidget<BWidget>(ref: const BWidget()),
        WWidget<CWidget>(ref: CWidget()),
        const WWidget<DWidget>(ref: DWidget()),
      ];
  // Bulk up list to reduce loop overheads.
  final List<Widget> widgets = _widgets() + _widgets() + _widgets();

  @override
  void exercise() => run();

  @override
  void run() {
    for (var w1 in widgets) {
      for (var w2 in widgets) {
        if (Widget.canUpdate(w1, w2) != Widget.canUpdate(w2, w1)) {
          throw 'Hmm $w1 $w2';
        }
      }
    }
  }

  // Normalize by number of calls to [Widgets.canUpdate].
  @override
  double measure() => super.measure() / (widgets.length * widgets.length * 2);
}

class ValueKeyEqualBenchmark extends BenchmarkBase {
  ValueKeyEqualBenchmark() : super('RuntimeType.Widget.canUpdate.byKey');

  // All widgets the same class but distinguished on keys.
  static List<Widget> _widgets() => [
        AWidget(),
        AWidget(key: ValueKey(1)),
        AWidget(key: ValueKey(1)),
        AWidget(key: ValueKey(2)),
        AWidget(key: ValueKey(2)),
        AWidget(key: ValueKey(3)),
        AWidget(key: ValueKey('one')),
        AWidget(key: ValueKey('two')),
        AWidget(key: ValueKey('three')),
        AWidget(key: ValueKey(Duration(seconds: 5))),
      ];
  // Bulk up list to reduce loop overheads.
  final List<Widget> widgets = _widgets() + _widgets() + _widgets();

  @override
  void exercise() => run();

  @override
  void run() {
    for (var w1 in widgets) {
      for (var w2 in widgets) {
        if (Widget.canUpdate(w1, w2) != Widget.canUpdate(w2, w1)) {
          throw 'Hmm $w1 $w2';
        }
      }
    }
  }

  // Normalize by number of calls to [Widgets.canUpdate].
  @override
  double measure() => super.measure() / (widgets.length * widgets.length * 2);
}

void pollute() {
  // Various bits of code to make environment less unrealistic.
  void check(dynamic a, dynamic b) {
    if (a.runtimeType != b.runtimeType) throw 'mismatch $a $b';
  }

  check(Uint8List(1), Uint8List(2)); // dart2js needs native interceptors.
  check(Int16List(1), Int16List(2));
  check([], []);
  check(<bool>{}, <bool>{});
}

void main() {
  pollute();

  final benchmarks = [
    WidgetCanUpdateBenchmark(),
    ValueKeyEqualBenchmark(),
  ];

  // Warm up all benchmarks before running any.
  benchmarks.forEach((bm) => bm.run());

  benchmarks.forEach((bm) => bm.report());
}
