// 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:async';
import 'dart:ui';

import 'package:flutter/gestures.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';

import 'recorder.dart';

class _NestedMouseRegion extends StatelessWidget {
  const _NestedMouseRegion({required this.nests, required this.child});

  final int nests;
  final Widget child;

  @override
  Widget build(BuildContext context) {
    Widget current = child;
    for (int i = 0; i < nests; i++) {
      current = MouseRegion(
        onEnter: (_) {},
        child: child,
      );
    }
    return current;
  }
}

/// Creates a grid of mouse regions, then continuously hover over them.
///
/// Measures our ability to hit test mouse regions.
class BenchMouseRegionGridHover extends WidgetRecorder {
  BenchMouseRegionGridHover() : super(name: benchmarkName) {
    _tester = _Tester(onDataPoint: handleDataPoint);
  }

  static const String benchmarkName = 'bench_mouse_region_grid_hover';

  late _Tester _tester;

  void handleDataPoint(Duration duration) {
    profile!.addDataPoint('hitTestDuration', duration, reported: true);
  }

  // Use a non-trivial border to force Web to switch painter
  Border _getBorder(int columnIndex, int rowIndex) {
    const BorderSide defaultBorderSide = BorderSide();

    return Border(
      left: columnIndex == 0 ? defaultBorderSide : BorderSide.none,
      top: rowIndex == 0 ? defaultBorderSide : BorderSide.none,
      right: defaultBorderSide,
      bottom: defaultBorderSide,
    );
  }

  bool started = false;

  @override
  void frameDidDraw() {
    if (!started) {
      started = true;
      SchedulerBinding.instance!.addPostFrameCallback((Duration timeStamp) async {
        _tester.start();
        registerDidStop(_tester.stop);
      });
    }
    super.frameDidDraw();
  }

  @override
  Widget createWidget() {
    const int rowsCount = 60;
    const int columnsCount = 20;
    const double containerSize = 20;
    return Directionality(
      textDirection: TextDirection.ltr,
      child: Align(
        alignment: Alignment.topLeft,
        child: SizedBox(
          width: 400,
          height: 400,
          child: ListView.builder(
            itemCount: rowsCount,
            cacheExtent: rowsCount * containerSize,
            physics: const ClampingScrollPhysics(),
            itemBuilder: (BuildContext context, int rowIndex) => _NestedMouseRegion(
              nests: 10,
              child: Row(
                children: List<Widget>.generate(
                  columnsCount,
                  (int columnIndex) => _NestedMouseRegion(
                    nests: 10,
                    child: Container(
                      decoration: BoxDecoration(
                        border: _getBorder(columnIndex, rowIndex),
                        color: Color.fromARGB(255, rowIndex * 20 % 256, 127, 127),
                      ),
                      width: containerSize,
                      height: containerSize,
                    ),
                  ),
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }
}

class _UntilNextFrame {
  _UntilNextFrame._();

  static Completer<void>? _completer;

  static Future<void> wait() {
    if (_UntilNextFrame._completer == null) {
      _UntilNextFrame._completer = Completer<void>();
      SchedulerBinding.instance!.addPostFrameCallback((_) {
        _UntilNextFrame._completer!.complete(null);
        _UntilNextFrame._completer = null;
      });
    }
    return _UntilNextFrame._completer!.future;
  }
}

class _Tester {
  _Tester({required this.onDataPoint});

  final ValueSetter<Duration> onDataPoint;

  static const Duration hoverDuration = Duration(milliseconds: 20);

  bool _stopped = false;

  TestGesture get gesture {
    return _gesture ??= TestGesture(
      dispatcher: (PointerEvent event) async {
        RendererBinding.instance!.handlePointerEvent(event);
      },
      kind: PointerDeviceKind.mouse,
    );
  }
  TestGesture? _gesture;

  Duration currentTime = Duration.zero;

  Future<void> _hoverTo(Offset location, Duration duration) async {
    currentTime += duration;
    final Stopwatch stopwatch = Stopwatch()..start();
    await gesture.moveTo(location, timeStamp: currentTime);
    stopwatch.stop();
    if (onDataPoint != null)
      onDataPoint(stopwatch.elapsed);
    await _UntilNextFrame.wait();
  }

  Future<void> start() async {
    await Future<void>.delayed(Duration.zero);
    while (!_stopped) {
      await _hoverTo(const Offset(30, 10), hoverDuration);
      await _hoverTo(const Offset(10, 370), hoverDuration);
      await _hoverTo(const Offset(370, 390), hoverDuration);
      await _hoverTo(const Offset(390, 30), hoverDuration);
    }
  }

  void stop() {
    _stopped = true;
  }
}
