// 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/widgets.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter_test/flutter_test.dart';

import 'recorder.dart';

class _NestedMouseRegion extends StatelessWidget {
  const _NestedMouseRegion({this.nests, 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;
  }
}

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

  final int nests;
  final Widget child;

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

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

  static const String benchmarkName = 'bench_mouse_region_mixed_grid_hover';

  _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) => _NestedListener(
                    nests: 40,
                    child: _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({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;
  }
}
