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

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

import 'semantics_tester.dart';

typedef TraversalTestFunction = Future<void> Function(TraversalTester tester);
const Size tenByTen = Size(10.0, 10.0);

void main() {
  setUp(() {
    debugResetSemanticsIdCounter();
  });

  void testTraversal(String description, TraversalTestFunction testFunction) {
    testWidgets(description, (WidgetTester tester) async {
      final TraversalTester traversalTester = TraversalTester(tester);
      await testFunction(traversalTester);
      traversalTester.dispose();
    });
  }

  // ┌───┐ ┌───┐
  // │ A │>│ B │
  // └───┘ └───┘
  testTraversal('Semantics traverses horizontally left-to-right', (TraversalTester tester) async {
    await tester.test(
      textDirection: TextDirection.ltr,
      children: <String, Rect>{
        'A': const Offset(0.0, 0.0) & tenByTen,
        'B': const Offset(20.0, 0.0) & tenByTen,
      },
      expectedTraversal: 'A B',
    );
  });

  // ┌───┐ ┌───┐
  // │ A │<│ B │
  // └───┘ └───┘
  testTraversal('Semantics traverses horizontally right-to-left', (TraversalTester tester) async {
    await tester.test(
      textDirection: TextDirection.rtl,
      children: <String, Rect>{
        'A': const Offset(0.0, 0.0) & tenByTen,
        'B': const Offset(20.0, 0.0) & tenByTen,
      },
      expectedTraversal: 'B A',
    );
  });

  // ┌───┐
  // │ A │
  // └───┘
  //   V
  // ┌───┐
  // │ B │
  // └───┘
  testTraversal('Semantics traverses vertically top-to-bottom', (TraversalTester tester) async {
    for (final TextDirection textDirection in TextDirection.values) {
      await tester.test(
        textDirection: textDirection,
        children: <String, Rect>{
          'A': const Offset(0.0, 0.0) & tenByTen,
          'B': const Offset(0.0, 20.0) & tenByTen,
        },
        expectedTraversal: 'A B',
      );
    }
  });

  // ┌───┐ ┌───┐
  // │ A │>│ B │
  // └───┘ └───┘
  //   ┌─────┘
  //   V
  // ┌───┐ ┌───┐
  // │ C │>│ D │
  // └───┘ └───┘
  testTraversal('Semantics traverses a grid left-to-right', (TraversalTester tester) async {
    await tester.test(
      textDirection: TextDirection.ltr,
      children: <String, Rect>{
        'A': const Offset(0.0, 0.0) & tenByTen,
        'B': const Offset(20.0, 0.0) & tenByTen,
        'C': const Offset(0.0, 20.0) & tenByTen,
        'D': const Offset(20.0, 20.0) & tenByTen,
      },
      expectedTraversal: 'A B C D',
    );
  });

  // ┌───┐ ┌───┐
  // │ A │<│ B │
  // └───┘ └───┘
  //   └─────┐
  //         V
  // ┌───┐ ┌───┐
  // │ C │<│ D │
  // └───┘ └───┘
  testTraversal('Semantics traverses a grid right-to-left', (TraversalTester tester) async {
    await tester.test(
      textDirection: TextDirection.rtl,
      children: <String, Rect>{
        'A': const Offset(0.0, 0.0) & tenByTen,
        'B': const Offset(20.0, 0.0) & tenByTen,
        'C': const Offset(0.0, 20.0) & tenByTen,
        'D': const Offset(20.0, 20.0) & tenByTen,
      },
      expectedTraversal: 'B A D C',
    );
  });

  // ┌───┐           ┌───┐
  // │ A │           │ C │
  // └───┘<->┌───┐<->└───┘
  //         │ B │
  //         └───┘
  testTraversal('Semantics traverses vertically overlapping nodes horizontally', (TraversalTester tester) async {
    final Map<String, Rect> children = <String, Rect>{
      'A': const Offset(0.0, 0.0) & tenByTen,
      'B': const Offset(20.0, 5.0) & tenByTen,
      'C': const Offset(40.0, 0.0) & tenByTen,
    };

    await tester.test(
      textDirection: TextDirection.ltr,
      children: children,
      expectedTraversal: 'A B C',
    );

    await tester.test(
      textDirection: TextDirection.rtl,
      children: children,
      expectedTraversal: 'C B A',
    );
  });

  // LTR:
  // ┌───┐ ┌───┐ ┌───┐ ┌───┐
  // │ A │>│ B │>│ C │>│ D │
  // └───┘ └───┘ └───┘ └───┘
  //   ┌─────────────────┘
  //   V
  // ┌───┐ ┌─────────┐ ┌───┐
  // │ E │>│         │>│ G │
  // └───┘ │    F    │ └───┘
  //   ┌───|─────────|───┘
  // ┌───┐ │         │ ┌───┐
  // │ H │─|─────────|>│ I │
  // └───┘ └─────────┘ └───┘
  //   ┌─────────────────┘
  //   V
  // ┌───┐ ┌───┐ ┌───┐ ┌───┐
  // │ J │>│ K │>│ L │>│ M │
  // └───┘ └───┘ └───┘ └───┘
  //
  // RTL:
  // ┌───┐ ┌───┐ ┌───┐ ┌───┐
  // │ A │<│ B │<│ C │<│ D │
  // └───┘ └───┘ └───┘ └───┘
  //   └─────────────────┐
  //                     V
  // ┌───┐ ┌─────────┐ ┌───┐
  // │ E │<│         │<│ G │
  // └───┘ │    F    │ └───┘
  //    └──|─────────|────┐
  // ┌───┐ │         │ ┌───┐
  // │ H │<|─────────|─│ I │
  // └───┘ └─────────┘ └───┘
  //   └─────────────────┐
  //                     V
  // ┌───┐ ┌───┐ ┌───┐ ┌───┐
  // │ J │<│ K │<│ L │<│ M │
  // └───┘ └───┘ └───┘ └───┘
  testTraversal('Semantics traverses vertical groups, then horizontal groups, then knots', (TraversalTester tester) async {
    final Map<String, Rect> children = <String, Rect>{
      'A': const Offset(0.0, 0.0) & tenByTen,
      'B': const Offset(20.0, 0.0) & tenByTen,
      'C': const Offset(40.0, 0.0) & tenByTen,
      'D': const Offset(60.0, 0.0) & tenByTen,
      'E': const Offset(0.0, 20.0) & tenByTen,
      'F': const Offset(20.0, 20.0) & (tenByTen * 2.0),
      'G': const Offset(60.0, 20.0) & tenByTen,
      'H': const Offset(0.0, 40.0) & tenByTen,
      'I': const Offset(60.0, 40.0) & tenByTen,
      'J': const Offset(0.0, 60.0) & tenByTen,
      'K': const Offset(20.0, 60.0) & tenByTen,
      'L': const Offset(40.0, 60.0) & tenByTen,
      'M': const Offset(60.0, 60.0) & tenByTen,
    };

    await tester.test(
      textDirection: TextDirection.ltr,
      children: children,
      expectedTraversal: 'A B C D E F G H I J K L M',
    );

    await tester.test(
      textDirection: TextDirection.rtl,
      children: children,
      expectedTraversal: 'D C B A G F E I H M L K J',
    );
  });

  // The following test tests traversal of the simplest "knot", which is two
  // nodes overlapping both vertically and horizontally. For example:
  //
  // ┌─────────┐
  // │         │
  // │   A     │
  // │     ┌───┼─────┐
  // │     │   │     │
  // └─────┼───┘     │
  //       │     B   │
  //       │         │
  //       └─────────┘
  //
  // The outcome depends on the relative positions of the centers of `Rect`s of
  // their respective boxes, specifically the direction (i.e. angle) of the
  // vector pointing from A to B. We test different angles, one for each octant:
  //
  //  -3π/4 -π/2  -π/4
  //      ╲   │   ╱
  //       ╲ 1│2 ╱
  //        ╲ │ ╱
  //     i=0 ╲│╱ 3
  //  π ──────┼────── 0
  //       7 ╱│╲ 4
  //        ╱ │ ╲
  //       ╱ 6│5 ╲
  //      ╱   │   ╲
  //   3π/4  π/2   π/4
  //
  // For LTR, angles falling into octants 3, 4, 5, and 6, produce A -> B, all
  // others produce B -> A.
  //
  // For RTL, angles falling into octants 5, 6, 7, and 0, produce A -> B, all
  // others produce B -> A.
  testTraversal('Semantics sorts knots', (TraversalTester tester) async {
    const double start = -math.pi + math.pi / 8.0;

    for (int i = 0; i < 8; i += 1) {
      final double angle = start + i.toDouble() * math.pi / 4.0;
      // These values should be truncated so that double precision rounding
      // issues won't impact the heights/widths and throw off the traversal
      // ordering.
      final double dx = (math.cos(angle) * 15.0) / 10.0;
      final double dy = (math.sin(angle) * 15.0) / 10.0;

      final Map<String, Rect> children = <String, Rect>{
        'A': const Offset(10.0, 10.0) & tenByTen,
        'B': Offset(10.0 + dx, 10.0 + dy) & tenByTen,
      };

      try {
        await tester.test(
          textDirection: TextDirection.ltr,
          children: children,
          expectedTraversal: 3 <= i && i <= 6 ? 'A B' : 'B A',
        );

        await tester.test(
          textDirection: TextDirection.rtl,
          children: children,
          expectedTraversal: 1 <= i && i <= 4 ? 'B A' : 'A B',
        );
      } catch (error) {
        fail(
          'Test failed with i == $i, angle == ${angle / math.pi}π\n'
          '$error'
        );
      }
    }
  });
}

class TraversalTester {
  TraversalTester(this.tester) : semantics = SemanticsTester(tester);

  final WidgetTester tester;
  final SemanticsTester semantics;

  Future<void> test({
    required TextDirection textDirection,
    required Map<String, Rect> children,
    required String expectedTraversal,
  }) async {
    assert(children is LinkedHashMap);
    await tester.pumpWidget(
        Container(
            child: Directionality(
              textDirection: textDirection,
              child: Semantics(
                textDirection: textDirection,
                child: CustomMultiChildLayout(
                  delegate: TestLayoutDelegate(children),
                  children: children.keys.map<Widget>((String label) {
                    return LayoutId(
                      id: label,
                      child: Semantics(
                        container: true,
                        explicitChildNodes: true,
                        label: label,
                        child: SizedBox(
                          width: children[label]!.width,
                          height: children[label]!.height,
                        ),
                      ),
                    );
                  }).toList(),
                ),
              ),
            ),
        ),
    );

    expect(semantics, hasSemantics(
      TestSemantics.root(
        children: <TestSemantics>[
          TestSemantics.rootChild(
            textDirection: textDirection,
            children: expectedTraversal.split(' ').map<TestSemantics>((String label) {
              return TestSemantics(
                label: label,
              );
            }).toList(),
          ),
        ],
      ),
      ignoreTransform: true,
      ignoreRect: true,
      ignoreId: true,
      childOrder: DebugSemanticsDumpOrder.traversalOrder,
    ));
  }

  void dispose() {
    semantics.dispose();
  }
}

class TestLayoutDelegate extends MultiChildLayoutDelegate {

  TestLayoutDelegate(this.children);

  final Map<String, Rect> children;

  @override
  void performLayout(Size size) {
    children.forEach((String label, Rect rect) {
      layoutChild(label, BoxConstraints.loose(size));
      positionChild(label, rect.topLeft);
    });
  }

  @override
  bool shouldRelayout(MultiChildLayoutDelegate oldDelegate) => oldDelegate == this;
}
