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

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

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

class TestImageProvider extends ImageProvider<TestImageProvider> {
  TestImageProvider(this.future);

  final Future<void> future;

  static late ui.Image image;

  @override
  Future<TestImageProvider> obtainKey(ImageConfiguration configuration) {
    return SynchronousFuture<TestImageProvider>(this);
  }

  @override
  ImageStreamCompleter load(TestImageProvider key, DecoderCallback decode) {
    return OneFrameImageStreamCompleter(
      future.then<ImageInfo>((void value) => ImageInfo(image: image)),
    );
  }
}

Future<void> main() async {
  AutomatedTestWidgetsFlutterBinding();
  TestImageProvider.image = await decodeImageFromList(Uint8List.fromList(kTransparentImage));

  testWidgets('DecoratedBox handles loading images', (WidgetTester tester) async {
    final GlobalKey key = GlobalKey();
    final Completer<void> completer = Completer<void>();
    await tester.pumpWidget(
      KeyedSubtree(
        key: key,
        child: DecoratedBox(
          decoration: BoxDecoration(
            image: DecorationImage(
              image: TestImageProvider(completer.future),
            ),
          ),
        ),
      ),
    );
    expect(tester.binding.hasScheduledFrame, isFalse);
    completer.complete();
    await tester.idle();
    expect(tester.binding.hasScheduledFrame, isTrue);
    await tester.pump();
    expect(tester.binding.hasScheduledFrame, isFalse);
  });

  testWidgets('Moving a DecoratedBox', (WidgetTester tester) async {
    final Completer<void> completer = Completer<void>();
    final Widget subtree = KeyedSubtree(
      key: GlobalKey(),
      child: RepaintBoundary(
        child: DecoratedBox(
          decoration: BoxDecoration(
            image: DecorationImage(
              image: TestImageProvider(completer.future),
            ),
          ),
        ),
      ),
    );
    await tester.pumpWidget(subtree);
    await tester.idle();
    expect(tester.binding.hasScheduledFrame, isFalse);
    await tester.pumpWidget(Container(child: subtree));
    await tester.idle();
    expect(tester.binding.hasScheduledFrame, isFalse);
    completer.complete(); // schedules microtask, does not run it
    expect(tester.binding.hasScheduledFrame, isFalse);
    await tester.idle(); // runs microtask
    expect(tester.binding.hasScheduledFrame, isTrue);
    await tester.pump();
    await tester.idle();
    expect(tester.binding.hasScheduledFrame, isFalse);
  });

  testWidgets('Circles can have uniform borders', (WidgetTester tester) async {
    await tester.pumpWidget(
      Container(
        padding: const EdgeInsets.all(50.0),
        decoration: BoxDecoration(
          shape: BoxShape.circle,
          border: Border.all(width: 10.0, color: const Color(0x80FF00FF)),
          color: Colors.teal[600],
        ),
      ),
    );
  });

  testWidgets('Bordered Container insets its child', (WidgetTester tester) async {
    const Key key = Key('outerContainer');
    await tester.pumpWidget(
      Center(
        child: Container(
          key: key,
          decoration: BoxDecoration(border: Border.all(width: 10.0)),
          child: const SizedBox(
            width: 25.0,
            height: 25.0,
          ),
        ),
      ),
    );
    expect(tester.getSize(find.byKey(key)), equals(const Size(45.0, 45.0)));
  });

  testWidgets('BoxDecoration paints its border correctly', (WidgetTester tester) async {
    // Regression test for https://github.com/flutter/flutter/issues/7672

    const Key key = Key('Container with BoxDecoration');
    Widget buildFrame(Border border) {
      return Center(
        child: Container(
          key: key,
          width: 100.0,
          height: 50.0,
          decoration: BoxDecoration(border: border),
        ),
      );
    }

    const Color black = Color(0xFF000000);

    await tester.pumpWidget(buildFrame(Border.all()));
    expect(find.byKey(key), paints..rect(color: black, style: PaintingStyle.stroke, strokeWidth: 1.0));

    await tester.pumpWidget(buildFrame(Border.all(width: 0.0)));
    expect(find.byKey(key), paints..rect(color: black, style: PaintingStyle.stroke, strokeWidth: 0.0));

    const Color green = Color(0xFF00FF00);
    const BorderSide greenSide = BorderSide(color: green, width: 10.0);

    await tester.pumpWidget(buildFrame(const Border(top: greenSide)));
    expect(find.byKey(key), paints..path(color: green, style: PaintingStyle.fill));

    await tester.pumpWidget(buildFrame(const Border(left: greenSide)));
    expect(find.byKey(key), paints..path(color: green, style: PaintingStyle.fill));

    await tester.pumpWidget(buildFrame(const Border(right: greenSide)));
    expect(find.byKey(key), paints..path(color: green, style: PaintingStyle.fill));

    await tester.pumpWidget(buildFrame(const Border(bottom: greenSide)));
    expect(find.byKey(key), paints..path(color: green, style: PaintingStyle.fill));

    const Color blue = Color(0xFF0000FF);
    const BorderSide blueSide = BorderSide(color: blue, width: 0.0);

    await tester.pumpWidget(buildFrame(const Border(top: blueSide, right: greenSide, bottom: greenSide)));
    expect(
      find.byKey(key),
      paints
        ..path() // There's not much point checking the arguments to these calls because paintBorder
        ..path() // reuses the same Paint object each time, configured differently, and so they will
        ..path(), // all appear to have the same settings here (that of the last call).
    );
  });

  testWidgets('BoxDecoration paints its border correctly', (WidgetTester tester) async {
    // Regression test for https://github.com/flutter/flutter/issues/12165
    await tester.pumpWidget(
      Column(
        children: <Widget>[
          Container(
            // There's not currently a way to verify that this paints the same size as the others,
            // so the pattern below just asserts that there's four paths but doesn't check the geometry.
            width: 100.0,
            height: 100.0,
            decoration: const BoxDecoration(
              border: Border(
                top: BorderSide(
                  width: 10.0,
                  color: Color(0xFFEEEEEE),
                ),
                left: BorderSide(
                  width: 10.0,
                  color: Color(0xFFFFFFFF),
                ),
                right: BorderSide(
                  width: 10.0,
                  color: Color(0xFFFFFFFF),
                ),
                bottom: BorderSide(
                  width: 10.0,
                  color: Color(0xFFFFFFFF),
                ),
              ),
            ),
          ),
          Container(
            width: 100.0,
            height: 100.0,
            decoration: BoxDecoration(
              border: Border.all(
                width: 10.0,
                color: const Color(0xFFFFFFFF),
              ),
            ),
          ),
          Container(
            width: 100.0,
            height: 100.0,
            decoration: BoxDecoration(
              border: Border.all(
                width: 10.0,
                color: const Color(0xFFFFFFFF),
              ),
              borderRadius: const BorderRadius.only(
                topRight: Radius.circular(10.0),
              ),
            ),
          ),
          Container(
            width: 100.0,
            height: 100.0,
            decoration: BoxDecoration(
              border: Border.all(
                width: 10.0,
                color: const Color(0xFFFFFFFF),
              ),
              shape: BoxShape.circle,
            ),
          ),
        ],
      ),
    );
    expect(find.byType(Column), paints
      ..path()
      ..path()
      ..path()
      ..path()
      ..rect(rect: const Rect.fromLTRB(355.0, 105.0, 445.0, 195.0))
      ..drrect(
        outer: RRect.fromLTRBAndCorners(
          350.0, 200.0, 450.0, 300.0,
          topRight: const Radius.circular(10.0),
        ),
        inner: RRect.fromLTRBAndCorners(
          360.0, 210.0, 440.0, 290.0,
          topLeft: const Radius.circular(-10.0),
          bottomRight: const Radius.circular(-10.0),
          bottomLeft: const Radius.circular(-10.0),
        ),
      )
      ..circle(x: 400.0, y: 350.0, radius: 45.0),
    );
  });

  testWidgets('Can hit test on BoxDecoration', (WidgetTester tester) async {

    late List<int> itemsTapped;

    const Key key = Key('Container with BoxDecoration');
    Widget buildFrame(Border border) {
      itemsTapped = <int>[];
      return Center(
        child: GestureDetector(
          behavior: HitTestBehavior.deferToChild,
          child: Container(
            key: key,
            width: 100.0,
            height: 50.0,
            decoration: BoxDecoration(border: border),
          ),
          onTap: () {
            itemsTapped.add(1);
          },
        ),
      );
    }

    await tester.pumpWidget(buildFrame(Border.all()));
    expect(itemsTapped, isEmpty);

    await tester.tap(find.byKey(key));
    expect(itemsTapped, <int>[1]);

    await tester.tapAt(const Offset(350.0, 275.0));
    expect(itemsTapped, <int>[1,1]);

    await tester.tapAt(const Offset(449.0, 324.0));
    expect(itemsTapped, <int>[1,1,1]);

  });

  testWidgets('Can hit test on BoxDecoration circle', (WidgetTester tester) async {

    late List<int> itemsTapped;

    const Key key = Key('Container with BoxDecoration');
    Widget buildFrame(Border border) {
      itemsTapped = <int>[];
      return Center(
        child: GestureDetector(
            behavior: HitTestBehavior.deferToChild,
            child: Container(
            key: key,
            width: 100.0,
            height: 50.0,
            decoration: BoxDecoration(border: border, shape: BoxShape.circle),
          ),
          onTap: () {
            itemsTapped.add(1);
          },
        ),
      );
    }

    await tester.pumpWidget(buildFrame(Border.all()));
    expect(itemsTapped, isEmpty);

    await tester.tapAt(Offset.zero);
    expect(itemsTapped, isEmpty);

    await tester.tapAt(const Offset(350.0, 275.0));
    expect(itemsTapped, isEmpty);

    await tester.tapAt(const Offset(400.0, 300.0));
    expect(itemsTapped, <int>[1]);

    await tester.tap(find.byKey(key));
    expect(itemsTapped, <int>[1,1]);

  });

  testWidgets('Can hit test on BoxDecoration border', (WidgetTester tester) async {
    late List<int> itemsTapped;
    const Key key = Key('Container with BoxDecoration');
    Widget buildFrame(Border border) {
      itemsTapped = <int>[];
      return Center(
        child: GestureDetector(
          behavior: HitTestBehavior.deferToChild,
          child: Container(
            key: key,
            width: 100.0,
            height: 50.0,
            decoration: BoxDecoration(border: border, borderRadius: const BorderRadius.all(Radius.circular(20.0))),
          ),
          onTap: () {
            itemsTapped.add(1);
          },
        ),
      );
    }

    await tester.pumpWidget(buildFrame(Border.all()));

    expect(itemsTapped, isEmpty);

    await tester.tapAt(Offset.zero);
    expect(itemsTapped, isEmpty);

    await tester.tapAt(const Offset(350.0, 275.0));
    expect(itemsTapped, isEmpty);

    await tester.tapAt(const Offset(400.0, 300.0));
    expect(itemsTapped, <int>[1]);

    await tester.tap(find.byKey(key));
    expect(itemsTapped, <int>[1,1]);
  });

  testWidgets('BoxDecoration not tap outside rounded angles - Top Left', (WidgetTester tester) async {
    const double height = 50.0;
    const double width = 50.0;
    const double radius = 12.3;

    late List<int> itemsTapped;
    const Key key = Key('Container with BoxDecoration');
    Widget buildFrame(Border border) {
      itemsTapped = <int>[];
      return Align(
        alignment: Alignment.topLeft,
        child: GestureDetector(
          behavior: HitTestBehavior.deferToChild,
          child: Container(
            key: key,
            width: width,
            height: height,
            decoration: BoxDecoration(border: border,borderRadius: BorderRadius.circular(radius)),
          ),
          onTap: () {
            itemsTapped.add(1);
          },
        ),
      );
    }

    await tester.pumpWidget(buildFrame(Border.all()));

    expect(itemsTapped, isEmpty);
    // x, y
    const Offset topLeft = Offset.zero;
    const Offset borderTopTangent = Offset(radius-1, 0.0);
    const Offset borderLeftTangent = Offset(0.0,radius-1);
    //the borderDiagonalOffset is the backslash line
    //\\######@@@
    //#\\###@####
    //##\\@######
    //##@########
    //@##########
    //@##########
    const double borderDiagonalOffset = radius - radius * math.sqrt1_2;
    const Offset fartherBorderRadiusPoint = Offset(borderDiagonalOffset,borderDiagonalOffset);

    await tester.tapAt(topLeft);
    expect(itemsTapped, isEmpty, reason: 'top left tapped');

    await tester.tapAt(borderTopTangent);
    expect(itemsTapped, isEmpty, reason: 'border top tapped');

    await tester.tapAt(borderLeftTangent);
    expect(itemsTapped, isEmpty, reason: 'border left tapped');

    await tester.tapAt(fartherBorderRadiusPoint);
    expect(itemsTapped, isEmpty, reason: 'border center tapped');

    await tester.tap(find.byKey(key));
    expect(itemsTapped, <int>[1]);

  });

  testWidgets('BoxDecoration tap inside rounded angles - Top Left', (WidgetTester tester) async {
    const double height = 50.0;
    const double width = 50.0;
    const double radius = 12.3;

    late List<int> itemsTapped;
    const Key key = Key('Container with BoxDecoration');
    Widget buildFrame(Border border) {
      itemsTapped = <int>[];
      return Align(
        alignment: Alignment.topLeft,
        child: GestureDetector(
          behavior: HitTestBehavior.deferToChild,
          child: Container(
            key: key,
            width: width,
            height: height,
            decoration: BoxDecoration(border: border,borderRadius: BorderRadius.circular(radius)),
          ),
          onTap: () {
            itemsTapped.add(1);
          },
        ),
      );
    }

    await tester.pumpWidget(buildFrame(Border.all()));

    expect(itemsTapped, isEmpty);
    // x, y
    const Offset borderTopTangent = Offset(radius, 0.0);
    const Offset borderLeftTangent = Offset(0.0,radius);
    const double borderDiagonalOffset = radius - radius * math.sqrt1_2;
    const Offset fartherBorderRadiusPoint = Offset(borderDiagonalOffset+1,borderDiagonalOffset+1);

    await tester.tapAt(borderTopTangent);
    expect(itemsTapped, <int>[1], reason: 'border Top not tapped');

    await tester.tapAt(borderLeftTangent);
    expect(itemsTapped, <int>[1,1], reason: 'border Left not tapped');

    await tester.tapAt(fartherBorderRadiusPoint);
    expect(itemsTapped, <int>[1,1,1], reason: 'border center not tapped');

    await tester.tap(find.byKey(key));
    expect(itemsTapped, <int>[1,1,1,1]);
  });

  testWidgets('BoxDecoration rounded angles other corner works', (WidgetTester tester) async {
    const double height = 50.0;
    const double width = 50.0;
    const double radius = 20;

    late List<int> itemsTapped;
    const Key key = Key('Container with BoxDecoration');
    Widget buildFrame(Border border) {
      itemsTapped = <int>[];
      return Align(
        alignment: Alignment.topLeft,
        child: GestureDetector(
          behavior: HitTestBehavior.deferToChild,
          child: Container(
            key: key,
            width: width,
            height: height,
            decoration: BoxDecoration(border: border,borderRadius: BorderRadius.circular(radius)),
          ),
          onTap: () {
            itemsTapped.add(1);
          },
        ),
      );
    }

    await tester.pumpWidget(buildFrame(Border.all()));

    expect(itemsTapped, isEmpty);

    await tester.tap(find.byKey(key));
    expect(itemsTapped, <int>[1]);

    // x, y
    const Offset topRightOutside = Offset(width, 0.0);
    const Offset topRightInside = Offset(width-radius, radius);
    const Offset bottomRightOutside = Offset(width, height);
    const Offset bottomRightInside = Offset(width-radius, height-radius);
    const Offset bottomLeftOutside = Offset(0, height);
    const Offset bottomLeftInside = Offset(radius, height-radius);
    const Offset topLeftOutside = Offset.zero;
    const Offset topLeftInside = Offset(radius, radius);

    await tester.tapAt(topRightInside);
    expect(itemsTapped, <int>[1,1], reason: 'top right not tapped');

    await tester.tapAt(topRightOutside);
    expect(itemsTapped, <int>[1,1], reason: 'top right tapped');

    await tester.tapAt(bottomRightInside);
    expect(itemsTapped, <int>[1,1,1], reason: 'bottom right not tapped');

    await tester.tapAt(bottomRightOutside);
    expect(itemsTapped, <int>[1,1,1], reason: 'bottom right tapped');

    await tester.tapAt(bottomLeftInside);
    expect(itemsTapped, <int>[1,1,1,1], reason: 'bottom left not tapped');

    await tester.tapAt(bottomLeftOutside);
    expect(itemsTapped, <int>[1,1,1,1], reason: 'bottom left tapped');

    await tester.tapAt(topLeftInside);
    expect(itemsTapped, <int>[1,1,1,1,1], reason: 'top left not tapped');

    await tester.tapAt(topLeftOutside);
    expect(itemsTapped, <int>[1,1,1,1,1], reason: 'top left tapped');
  });

  testWidgets("BoxDecoration doesn't crash with BorderRadiusDirectional", (WidgetTester tester) async {
    // Regression test for https://github.com/flutter/flutter/issues/88039

    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Container(
          decoration: BoxDecoration(
            border: Border.all(),
            borderRadius: const BorderRadiusDirectional.all(
              Radius.circular(1.0),
            ),
          ),
        ),
      ),
    );
  });
}
