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

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

const double _crispText = 100.0; // this font size is selected to avoid needing any antialiasing.
const String _expText = 'Éxp'; // renders in the test font as:

// ########
// ########
// ########
//     ########
//
// ÉÉÉÉxxxxpppp

void main() {
  testWidgets('Default background', (WidgetTester tester) async {
    await tester.pumpWidget(const Align(
      alignment: Alignment.topLeft,
      child: Text(_expText, textDirection: TextDirection.ltr, style: TextStyle(color: Color(0xFF345678), fontSize: _crispText))),
    );
    await _expectColors(
      tester,
      find.byType(Align),
      <Color>{ const Color(0x00000000), const Color(0xFF345678) },
      <Offset, Color>{
        Offset.zero: const Color(0xFF345678), // the text
        const Offset(10, 10): const Color(0xFF345678), // the text
        const Offset(50, 95): const Color(0x00000000), // the background (under the É)
        const Offset(250, 50): const Color(0x00000000), // the text (above the p)
        const Offset(250, 95): const Color(0xFF345678), // the text (the p)
        const Offset(400, 400): const Color(0x00000000), // the background
        const Offset(799, 599): const Color(0x00000000), // the background
      },
    );
  }, skip: !canCaptureImage); // [intended] Test relies on captureImage, which is not supported on web currently.

  testWidgets('Default text color', (WidgetTester tester) async {
    await tester.pumpWidget(const ColoredBox(
      color: Color(0xFFABCDEF),
      child: Align(
        alignment: Alignment.topLeft,
          child: Text('Éxp', textDirection: TextDirection.ltr, style: TextStyle(fontSize: _crispText)),
        ),
      ),
    );
    await _expectColors(
      tester,
      find.byType(Align),
      <Color>{ const Color(0xFFABCDEF), const Color(0xFFFFFFFF) },
      <Offset, Color>{
        Offset.zero: const Color(0xFFFFFFFF), // the text
        const Offset(10, 10): const Color(0xFFFFFFFF), // the text
        const Offset(50, 95): const Color(0xFFABCDEF), // the background (under the É)
        const Offset(250, 50): const Color(0xFFABCDEF), // the text (above the p)
        const Offset(250, 95): const Color(0xFFFFFFFF), // the text (the p)
        const Offset(400, 400): const Color(0xFFABCDEF), // the background
        const Offset(799, 599): const Color(0xFFABCDEF), // the background
      },
    );
  }, skip: !canCaptureImage); // [intended] Test relies on captureImage, which is not supported on web currently.

  testWidgets('Default text selection color', (WidgetTester tester) async {
    final GlobalKey key = GlobalKey();
    await tester.pumpWidget(
      ColoredBox(
        color: const Color(0xFFFFFFFF),
        child: Directionality(
          textDirection: TextDirection.ltr,
          child: MediaQuery(
            data: const MediaQueryData(),
            child: Overlay(
              initialEntries: <OverlayEntry>[
                OverlayEntry(
                  builder: (BuildContext context) => SelectableRegion(
                    focusNode: FocusNode(),
                    selectionControls: emptyTextSelectionControls,
                    child: Align(
                      key: key,
                      alignment: Alignment.topLeft,
                      child: const Text('Éxp', textDirection: TextDirection.ltr, style: TextStyle(fontSize: _crispText)),
                    ),
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
    await _expectColors(
      tester,
      find.byType(Align),
      <Color>{ const Color(0xFFFFFFFF) },
    );
    // fake a "select all" event to select the text
    Actions.invoke(key.currentContext!, const SelectAllTextIntent(SelectionChangedCause.keyboard));
    await tester.pump();
    await _expectColors(
      tester,
      find.byType(Align),
      <Color>{ const Color(0xFFFFFFFF), const Color(0xFFBFBFBF) }, // 0x80808080 blended with 0xFFFFFFFF
      <Offset, Color>{
        Offset.zero: const Color(0xFFBFBFBF), // the selected text
        const Offset(10, 10): const Color(0xFFBFBFBF), // the selected text
        const Offset(50, 95): const Color(0xFFBFBFBF), // the selected background (under the É)
        const Offset(250, 50): const Color(0xFFBFBFBF), // the selected background (above the p)
        const Offset(250, 95): const Color(0xFFBFBFBF), // the selected text (the p)
        const Offset(400, 400): const Color(0xFFFFFFFF), // the background
        const Offset(799, 599): const Color(0xFFFFFFFF), // the background
      },
    );
  }, skip: !canCaptureImage); // [intended] Test relies on captureImage, which is not supported on web currently.
}

Color _getPixel(ByteData bytes, int x, int y, int width) {
  final int offset = (x + y * width) * 4;
  return Color.fromARGB(
    bytes.getUint8(offset + 3),
    bytes.getUint8(offset + 0),
    bytes.getUint8(offset + 1),
    bytes.getUint8(offset + 2),
  );
}

Future<void> _expectColors(WidgetTester tester, Finder finder, Set<Color> allowedColors, [ Map<Offset, Color>? spotChecks ]) async {
  final TestWidgetsFlutterBinding binding = tester.binding;
  final ui.Image image = (await binding.runAsync<ui.Image>(() => captureImage(finder.evaluate().single)))!;
  final ByteData bytes = (await binding.runAsync<ByteData?>(() => image.toByteData(format: ui.ImageByteFormat.rawStraightRgba)))!;
  final Set<int> actualColorValues = <int>{};
  for (int offset = 0; offset < bytes.lengthInBytes; offset += 4) {
    actualColorValues.add((bytes.getUint8(offset + 3) << 24) +
                          (bytes.getUint8(offset + 0) << 16) +
                          (bytes.getUint8(offset + 1) << 8) +
                          (bytes.getUint8(offset + 2)));
  }
  final Set<Color> actualColors = actualColorValues.map((int value) => Color(value)).toSet();
  expect(actualColors, allowedColors);
  spotChecks?.forEach((Offset position, Color expected) {
    assert(position.dx.round() >= 0);
    assert(position.dx.round() < image.width);
    assert(position.dy.round() >= 0);
    assert(position.dy.round() < image.height);
    final Offset precisePosition = position * tester.view.devicePixelRatio;
    final Color actual = _getPixel(bytes, precisePosition.dx.round(), precisePosition.dy.round(), image.width);
    expect(actual, expected, reason: 'Pixel at $position is $actual but expected $expected.');
  });
}
