// 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';

/// Creates a grid of mouse regions, then continuously scrolls them up and down.
///
/// Measures our ability to render mouse regions.
class BenchMouseRegionGridScroll extends WidgetRecorder {
  BenchMouseRegionGridScroll() : super(name: benchmarkName);

  static const String benchmarkName = 'bench_mouse_region_grid_scroll';

  final _Tester tester = _Tester();

  // 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) => Row(
              children: List<Widget>.generate(
                columnsCount,
                (int columnIndex) => MouseRegion(
                  onEnter: (_) {},
                  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 {
  static const int scrollFrequency = 60;
  static const Offset dragStartLocation = Offset(200, 200);
  static const Offset dragUpOffset = Offset(0, 200);
  static const Offset dragDownOffset = Offset(0, -200);
  static const Duration dragDuration = Duration(milliseconds: 200);

  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> _scroll(Offset start, Offset offset, Duration duration) async {
    final int durationMs = duration.inMilliseconds;
    final Duration fullFrameDuration = const Duration(seconds: 1) ~/ scrollFrequency;
    final int frameDurationMs = fullFrameDuration.inMilliseconds;

    final int fullFrames = duration.inMilliseconds ~/ frameDurationMs;
    final Offset fullFrameOffset = offset * ((frameDurationMs as double) / durationMs);

    final Duration finalFrameDuration = duration - fullFrameDuration * fullFrames;
    final Offset finalFrameOffset = offset - fullFrameOffset * (fullFrames as double);

    await gesture.down(start, timeStamp: currentTime);

    for (int frame = 0; frame < fullFrames; frame += 1) {
      currentTime += fullFrameDuration;
      await gesture.moveBy(fullFrameOffset, timeStamp: currentTime);
      await _UntilNextFrame.wait();
    }

    if (finalFrameOffset != Offset.zero) {
      currentTime += finalFrameDuration;
      await gesture.moveBy(finalFrameOffset, timeStamp: currentTime);
      await _UntilNextFrame.wait();
    }

    await gesture.up(timeStamp: currentTime);
  }

  Future<void> start() async {
    await Future<void>.delayed(Duration.zero);
    while (!_stopped) {
      await _scroll(dragStartLocation, dragUpOffset, dragDuration);
      await _scroll(dragStartLocation, dragDownOffset, dragDuration);
    }
  }

  void stop() {
    _stopped = true;
  }
}
