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

// This file is run as part of a reduced test set in CI on Mac and Windows
// machines.
@Tags(<String>['reduced-test-set'])
library;

import 'package:flutter/material.dart';
import 'package:flutter/src/foundation/constants.dart';
import 'package:flutter_test/flutter_test.dart';

import '../rendering/mock_canvas.dart';

void main() {
  testWidgets('InkSparkle in a Button compiles and does not crash', (WidgetTester tester) async {
    await tester.pumpWidget(MaterialApp(
      home: Scaffold(
        body: Center(
          child: ElevatedButton(
            style: ElevatedButton.styleFrom(splashFactory: InkSparkle.splashFactory),
            child: const Text('Sparkle!'),
            onPressed: () { },
          ),
        ),
      ),
    ));
    final Finder buttonFinder = find.text('Sparkle!');
    await tester.tap(buttonFinder);
    await tester.pump();
    await tester.pumpAndSettle();
  },
    skip: kIsWeb, // [intended] shaders are not yet supported for web.
  );

  testWidgets('InkSparkle default splashFactory paints with drawRect when bounded', (WidgetTester tester) async {
    await tester.pumpWidget(MaterialApp(
      home: Scaffold(
        body: Center(
          child: InkWell(
            splashFactory: InkSparkle.splashFactory,
            child: const Text('Sparkle!'),
            onTap: () { },
          ),
        ),
      ),
    ));
    final Finder buttonFinder = find.text('Sparkle!');
    await tester.tap(buttonFinder);
    await tester.pump();
    await tester.pump(const Duration(milliseconds: 200));

    final MaterialInkController material = Material.of(tester.element(buttonFinder));
    expect(material, paintsExactlyCountTimes(#drawRect, 1));

    // ignore: avoid_dynamic_calls
    expect((material as dynamic).debugInkFeatures, hasLength(1));

    await tester.pumpAndSettle();
    // ink feature is disposed.
    // ignore: avoid_dynamic_calls
    expect((material as dynamic).debugInkFeatures, isEmpty);
  },
    skip: kIsWeb, // [intended] shaders are not yet supported for web.
  );

  testWidgets('InkSparkle default splashFactory paints with drawPaint when unbounded', (WidgetTester tester) async {
    await tester.pumpWidget(MaterialApp(
      home: Scaffold(
        body: Center(
          child: InkResponse(
            splashFactory: InkSparkle.splashFactory,
            child: const Text('Sparkle!'),
            onTap: () { },
          ),
        ),
      ),
    ));
    final Finder buttonFinder = find.text('Sparkle!');
    await tester.tap(buttonFinder);
    await tester.pump();
    await tester.pump(const Duration(milliseconds: 200));

    final MaterialInkController material = Material.of(tester.element(buttonFinder));
    expect(material, paintsExactlyCountTimes(#drawPaint, 1));
  },
    skip: kIsWeb, // [intended] shaders are not yet supported for web.
  );

  /////////////
  // Goldens //
  /////////////

  testWidgets('InkSparkle renders with sparkles when top left of button is tapped', (WidgetTester tester) async {
    await _runTest(tester, 'top_left', 0.2);
  },
    skip: kIsWeb, // [intended] shaders are not yet supported for web.
  );

  testWidgets('InkSparkle renders with sparkles when center of button is tapped', (WidgetTester tester) async {
    await _runTest(tester, 'center', 0.5);
  },
    skip: kIsWeb, // [intended] shaders are not yet supported for web.
  );

  testWidgets('InkSparkle renders with sparkles when bottom right of button is tapped', (WidgetTester tester) async {
    await _runTest(tester, 'bottom_right', 0.8);
  },
    skip: kIsWeb, // [intended] shaders are not yet supported for web.
  );
}

Future<void> _runTest(WidgetTester tester, String positionName, double distanceFromTopLeft) async {
  final Key repaintKey = UniqueKey();
  final Key buttonKey = UniqueKey();

  await tester.pumpWidget(MaterialApp(
    home: Scaffold(
      body: Center(
        child: RepaintBoundary(
          key: repaintKey,
          child: ElevatedButton(
            key: buttonKey,
            style: ElevatedButton.styleFrom(splashFactory: InkSparkle.constantTurbulenceSeedSplashFactory),
            child: const Text('Sparkle!'),
            onPressed: () { },
          ),
        ),
      ),
    ),
  ));

  final Finder buttonFinder = find.byKey(buttonKey);
  final Finder repaintFinder = find.byKey(repaintKey);
  final Offset topLeft = tester.getTopLeft(buttonFinder);
  final Offset bottomRight = tester.getBottomRight(buttonFinder);

  await _warmUpShader(tester, buttonFinder);

  final Offset target = topLeft + (bottomRight - topLeft) * distanceFromTopLeft;
  await tester.tapAt(target);
  for (int i = 0; i <= 5; i++) {
    await tester.pump(const Duration(milliseconds: 50));
    await expectLater(
      repaintFinder,
      matchesGoldenFile('ink_sparkle.$positionName.$i.png'),
    );
  }
}

// Warm up shader. Compilation is of the order of 10 milliseconds and
// Animation is < 1000 milliseconds. Use 2000 milliseconds as a safety
// net to prevent flakiness.
Future<void> _warmUpShader(WidgetTester tester, Finder buttonFinder) async {
  await tester.tap(buttonFinder);
  await tester.pumpAndSettle(const Duration(milliseconds: 2000));
}
