// 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 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';

import 'semantics_tester.dart';

void main() {
  group('BlockSemantics', () {
    testWidgets('hides semantic nodes of siblings', (WidgetTester tester) async {
      final SemanticsTester semantics = SemanticsTester(tester);

      await tester.pumpWidget(Stack(
        textDirection: TextDirection.ltr,
        children: <Widget>[
          Semantics(
            label: 'layer#1',
            textDirection: TextDirection.ltr,
            child: Container(),
          ),
          const BlockSemantics(),
          Semantics(
            label: 'layer#2',
            textDirection: TextDirection.ltr,
            child: Container(),
          ),
        ],
      ));

      expect(semantics, isNot(includesNodeWith(label: 'layer#1')));

      await tester.pumpWidget(Stack(
        textDirection: TextDirection.ltr,
        children: <Widget>[
          Semantics(
            label: 'layer#1',
            textDirection: TextDirection.ltr,
            child: Container(),
          ),
        ],
      ));

      expect(semantics, includesNodeWith(label: 'layer#1'));

      semantics.dispose();
    });

    testWidgets('does not hides semantic nodes of siblings outside the current semantic boundary', (WidgetTester tester) async {
      final SemanticsTester semantics = SemanticsTester(tester);

      await tester.pumpWidget(Directionality(textDirection: TextDirection.ltr, child: Stack(
        children: <Widget>[
          Semantics(
            label: '#1',
            child: Container(),
          ),
          Semantics(
            label: '#2',
            container: true,
            explicitChildNodes: true,
            child: Stack(
              children: <Widget>[
                Semantics(
                  label: 'NOT#2.1',
                  child: Container(),
                ),
                Semantics(
                  label: '#2.2',
                  child: BlockSemantics(
                    child: Semantics(
                      container: true,
                      label: '#2.2.1',
                      child: Container(),
                    ),
                  ),
                ),
                Semantics(
                  label: '#2.3',
                  child: Container(),
                ),
              ],
            ),
          ),
          Semantics(
            label: '#3',
            child: Container(),
          ),
        ],
      )));

      expect(semantics, includesNodeWith(label: '#1'));
      expect(semantics, includesNodeWith(label: '#2'));
      expect(semantics, isNot(includesNodeWith(label:'NOT#2.1')));
      expect(semantics, includesNodeWith(label: '#2.2'));
      expect(semantics, includesNodeWith(label: '#2.2.1'));
      expect(semantics, includesNodeWith(label: '#2.3'));
      expect(semantics, includesNodeWith(label: '#3'));

      semantics.dispose();
    });

    testWidgets('node is semantic boundary and blocking previously painted nodes', (WidgetTester tester) async {
      final SemanticsTester semantics = SemanticsTester(tester);
      final GlobalKey stackKey = GlobalKey();

      await tester.pumpWidget(Directionality(textDirection: TextDirection.ltr, child: Stack(
        key: stackKey,
        children: <Widget>[
          Semantics(
            label: 'NOT#1',
            child: Container(),
          ),
          BoundaryBlockSemantics(
            child: Semantics(
              label: '#2.1',
              child: Container(),
            ),
          ),
          Semantics(
            label: '#3',
            child: Container(),
          ),
        ],
      )));

      expect(semantics, isNot(includesNodeWith(label: 'NOT#1')));
      expect(semantics, includesNodeWith(label: '#2.1'));
      expect(semantics, includesNodeWith(label: '#3'));

      semantics.dispose();
    });
  });
}

class BoundaryBlockSemantics extends SingleChildRenderObjectWidget {
  const BoundaryBlockSemantics({ Key? key, required Widget child }) : super(key: key, child: child);

  @override
  RenderBoundaryBlockSemantics createRenderObject(BuildContext context) => RenderBoundaryBlockSemantics();
}

class RenderBoundaryBlockSemantics extends RenderProxyBox {
  RenderBoundaryBlockSemantics();

  @override
  void describeSemanticsConfiguration(SemanticsConfiguration config) {
    super.describeSemanticsConfiguration(config);

    config
      ..isBlockingSemanticsOfPreviouslyPaintedNodes = true
      ..isSemanticBoundary = true;
  }
}
