// 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.

// @dart = 2.8

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

void main() {
  testWidgets('gets local coordinates', (WidgetTester tester) async {
    int tapCount = 0;
    int tapCancelCount = 0;
    final List<TapDownDetails> downDetails = <TapDownDetails>[];
    final List<TapUpDetails> upDetails = <TapUpDetails>[];

    final Key redContainer = UniqueKey();
    await tester.pumpWidget(
      Center(
        child: GestureDetector(
          onTap: () {
            tapCount++;
          },
          onTapCancel: () {
            tapCancelCount++;
          },
          onTapDown: (TapDownDetails details) {
            downDetails.add(details);
          },
          onTapUp: (TapUpDetails details) {
            upDetails.add(details);
          },
          child: Container(
            key: redContainer,
            width: 100,
            height: 150,
            color: Colors.red,
          ),
        ),
      ),
    );

    await tester.tapAt(tester.getCenter(find.byKey(redContainer)));
    expect(tapCount, 1);
    expect(tapCancelCount, 0);
    expect(downDetails.single.localPosition, const Offset(50, 75));
    expect(downDetails.single.globalPosition, const Offset(400, 300));
    expect(upDetails.single.localPosition, const Offset(50, 75));
    expect(upDetails.single.globalPosition, const Offset(400, 300));
  });

  testWidgets('kTouchSlop is evaluated in the global coordinate space when scaled up', (WidgetTester tester) async {
    int tapCount = 0;
    int tapCancelCount = 0;
    final List<TapDownDetails> downDetails = <TapDownDetails>[];
    final List<TapUpDetails> upDetails = <TapUpDetails>[];

    final Key redContainer = UniqueKey();
    await tester.pumpWidget(
        Center(
          child: Transform.scale(
            scale: 2.0,
            child: GestureDetector(
                onTap: () {
                  tapCount++;
                },
                onTapCancel: () {
                  tapCancelCount++;
                },
                onTapDown: (TapDownDetails details) {
                  downDetails.add(details);
                },
                onTapUp: (TapUpDetails details) {
                  upDetails.add(details);
                },
                child: Container(
                  key: redContainer,
                  width: 100,
                  height: 150,
                  color: Colors.red,
                ),
            ),
          ),
        ),
    );

    // Move just below kTouchSlop should recognize tap.
    TestGesture gesture = await tester.startGesture(tester.getCenter(find.byKey(redContainer)));
    await gesture.moveBy(const Offset(0, kTouchSlop - 1));
    await gesture.up();

    expect(tapCount, 1);
    expect(tapCancelCount, 0);
    expect(downDetails.single.localPosition, const Offset(50, 75));
    expect(downDetails.single.globalPosition, const Offset(400, 300));
    expect(upDetails.single.localPosition, const Offset(50, 75 + (kTouchSlop - 1) / 2.0));
    expect(upDetails.single.globalPosition, const Offset(400, 300 + (kTouchSlop - 1)));

    downDetails.clear();
    upDetails.clear();
    tapCount = 0;
    tapCancelCount = 0;

    // Move more then kTouchSlop should cancel.
    gesture = await tester.startGesture(tester.getCenter(find.byKey(redContainer)));
    await gesture.moveBy(const Offset(0, kTouchSlop + 1));
    await gesture.up();
    expect(tapCount, 0);
    expect(tapCancelCount, 1);
    expect(downDetails.single.localPosition, const Offset(50, 75));
    expect(downDetails.single.globalPosition, const Offset(400, 300));
    expect(upDetails, isEmpty);
  });

  testWidgets('kTouchSlop is evaluated in the global coordinate space when scaled down', (WidgetTester tester) async {
    int tapCount = 0;
    int tapCancelCount = 0;
    final List<TapDownDetails> downDetails = <TapDownDetails>[];
    final List<TapUpDetails> upDetails = <TapUpDetails>[];

    final Key redContainer = UniqueKey();
    await tester.pumpWidget(
        Center(
          child: Transform.scale(
            scale: 0.5,
            child: GestureDetector(
                onTap: () {
                  tapCount++;
                },
                onTapCancel: () {
                  tapCancelCount++;
                },
                onTapDown: (TapDownDetails details) {
                  downDetails.add(details);
                },
                onTapUp: (TapUpDetails details) {
                  upDetails.add(details);
                },
                child: Container(
                  key: redContainer,
                  width: 100,
                  height: 150,
                  color: Colors.red,
                ),
            ),
          ),
        ),
    );

    // Move just below kTouchSlop should recognize tap.
    TestGesture gesture = await tester.startGesture(tester.getCenter(find.byKey(redContainer)));
    await gesture.moveBy(const Offset(0, kTouchSlop - 1));
    await gesture.up();

    expect(tapCount, 1);
    expect(tapCancelCount, 0);
    expect(downDetails.single.localPosition, const Offset(50, 75));
    expect(downDetails.single.globalPosition, const Offset(400, 300));
    expect(upDetails.single.localPosition, const Offset(50, 75 + (kTouchSlop - 1) * 2.0));
    expect(upDetails.single.globalPosition, const Offset(400, 300 + (kTouchSlop - 1)));

    downDetails.clear();
    upDetails.clear();
    tapCount = 0;
    tapCancelCount = 0;

    // Move more then kTouchSlop should cancel.
    gesture = await tester.startGesture(tester.getCenter(find.byKey(redContainer)));
    await gesture.moveBy(const Offset(0, kTouchSlop + 1));
    await gesture.up();
    expect(tapCount, 0);
    expect(tapCancelCount, 1);
    expect(downDetails.single.localPosition, const Offset(50, 75));
    expect(downDetails.single.globalPosition, const Offset(400, 300));
    expect(upDetails, isEmpty);
  });
}
