// 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 '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({
    TextDirection textDirection,
    Map<String, Rect> children,
    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;
}
