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

import 'semantics_tester.dart';

void main() {
  testWidgets('Semantics can merge sibling group', (WidgetTester tester) async {
    final SemanticsTester semantics = SemanticsTester(tester);
    const SemanticsTag first = SemanticsTag('1');
    const SemanticsTag second = SemanticsTag('2');
    const SemanticsTag third = SemanticsTag('3');
    ChildSemanticsConfigurationsResult delegate(List<SemanticsConfiguration> configs) {
      expect(configs.length, 3);
      final ChildSemanticsConfigurationsResultBuilder builder = ChildSemanticsConfigurationsResultBuilder();
      final List<SemanticsConfiguration> sibling = <SemanticsConfiguration>[];
      // Merge first and third
      for (final SemanticsConfiguration config in configs) {
        if (config.tagsChildrenWith(first) || config.tagsChildrenWith(third)) {
          sibling.add(config);
        } else {
          builder.markAsMergeUp(config);
        }
      }
      builder.markAsSiblingMergeGroup(sibling);
      return builder.build();
    }
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Semantics(
          label: 'parent',
          child: TestConfigDelegate(
            delegate: delegate,
            child: Column(
              children: <Widget>[
                Semantics(
                  label: '1',
                  tagForChildren: first,
                  child: const SizedBox(width: 100, height: 100),
                  // this tests that empty nodes disappear
                ),
                Semantics(
                  label: '2',
                  tagForChildren: second,
                  child: const SizedBox(width: 100, height: 100),
                ),
                Semantics(
                  label: '3',
                  tagForChildren: third,
                  child: const SizedBox(width: 100, height: 100),
                ),
              ],
            ),
          ),
        ),
      ),
    );

    expect(semantics, hasSemantics(TestSemantics.root(
      children: <TestSemantics>[
        TestSemantics.rootChild(
          label: 'parent\n2',
        ),
        TestSemantics.rootChild(
          label: '1\n3',
        ),
      ],
    ), ignoreId: true, ignoreRect: true, ignoreTransform: true));
  });

  testWidgets('Semantics can drop semantics config', (WidgetTester tester) async {
    final SemanticsTester semantics = SemanticsTester(tester);
    const SemanticsTag first = SemanticsTag('1');
    const SemanticsTag second = SemanticsTag('2');
    const SemanticsTag third = SemanticsTag('3');
    ChildSemanticsConfigurationsResult delegate(List<SemanticsConfiguration> configs) {
      final ChildSemanticsConfigurationsResultBuilder builder = ChildSemanticsConfigurationsResultBuilder();
      // Merge first and third
      for (final SemanticsConfiguration config in configs) {
        if (config.tagsChildrenWith(first) || config.tagsChildrenWith(third)) {
          continue;
        }
        builder.markAsMergeUp(config);
      }
      return builder.build();
    }
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Semantics(
          label: 'parent',
          child: TestConfigDelegate(
            delegate: delegate,
            child: Column(
              children: <Widget>[
                Semantics(
                  label: '1',
                  tagForChildren: first,
                  child: const SizedBox(width: 100, height: 100),
                  // this tests that empty nodes disappear
                ),
                Semantics(
                  label: '2',
                  tagForChildren: second,
                  child: const SizedBox(width: 100, height: 100),
                ),
                Semantics(
                  label: '3',
                  tagForChildren: third,
                  child: const SizedBox(width: 100, height: 100),
                ),
              ],
            ),
          ),
        ),
      ),
    );

    expect(semantics, hasSemantics(TestSemantics.root(
      children: <TestSemantics>[
        TestSemantics.rootChild(
          label: 'parent\n2',
        ),
      ],
    ), ignoreId: true, ignoreRect: true, ignoreTransform: true));
  });

  testWidgets('Semantics throws when mark the same config twice case 1', (WidgetTester tester) async {
    const SemanticsTag first = SemanticsTag('1');
    const SemanticsTag second = SemanticsTag('2');
    const SemanticsTag third = SemanticsTag('3');
    ChildSemanticsConfigurationsResult delegate(List<SemanticsConfiguration> configs) {
      final ChildSemanticsConfigurationsResultBuilder builder = ChildSemanticsConfigurationsResultBuilder();
      // Marks the same one twice.
      builder.markAsMergeUp(configs.first);
      builder.markAsMergeUp(configs.first);
      return builder.build();
    }
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Semantics(
          label: 'parent',
          child: TestConfigDelegate(
            delegate: delegate,
            child: Column(
              children: <Widget>[
                Semantics(
                  label: '1',
                  tagForChildren: first,
                  child: const SizedBox(width: 100, height: 100),
                  // this tests that empty nodes disappear
                ),
                Semantics(
                  label: '2',
                  tagForChildren: second,
                  child: const SizedBox(width: 100, height: 100),
                ),
                Semantics(
                  label: '3',
                  tagForChildren: third,
                  child: const SizedBox(width: 100, height: 100),
                ),
              ],
            ),
          ),
        ),
      ),
    );

    expect(tester.takeException(), isAssertionError);
  });

  testWidgets('Semantics throws when mark the same config twice case 2', (WidgetTester tester) async {
    const SemanticsTag first = SemanticsTag('1');
    const SemanticsTag second = SemanticsTag('2');
    const SemanticsTag third = SemanticsTag('3');
    ChildSemanticsConfigurationsResult delegate(List<SemanticsConfiguration> configs) {
      final ChildSemanticsConfigurationsResultBuilder builder = ChildSemanticsConfigurationsResultBuilder();
      // Marks the same one twice.
      builder.markAsMergeUp(configs.first);
      builder.markAsSiblingMergeGroup(<SemanticsConfiguration>[configs.first]);
      return builder.build();
    }
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: Semantics(
          label: 'parent',
          child: TestConfigDelegate(
            delegate: delegate,
            child: Column(
              children: <Widget>[
                Semantics(
                  label: '1',
                  tagForChildren: first,
                  child: const SizedBox(width: 100, height: 100),
                  // this tests that empty nodes disappear
                ),
                Semantics(
                  label: '2',
                  tagForChildren: second,
                  child: const SizedBox(width: 100, height: 100),
                ),
                Semantics(
                  label: '3',
                  tagForChildren: third,
                  child: const SizedBox(width: 100, height: 100),
                ),
              ],
            ),
          ),
        ),
      ),
    );

    expect(tester.takeException(), isAssertionError);
  });

  testWidgets('RenderObject with semantics child delegate will mark correct boundary dirty', (WidgetTester tester) async {
    final UniqueKey inner = UniqueKey();
    final UniqueKey boundaryParent = UniqueKey();
    final UniqueKey grandBoundaryParent = UniqueKey();
    ChildSemanticsConfigurationsResult delegate(List<SemanticsConfiguration> configs) {
      final ChildSemanticsConfigurationsResultBuilder builder = ChildSemanticsConfigurationsResultBuilder();
      configs.forEach(builder.markAsMergeUp);
      return builder.build();
    }
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: MarkSemanticsDirtySpy(
          key: grandBoundaryParent,
          child: MarkSemanticsDirtySpy(
            key: boundaryParent,
            child: TestConfigDelegate(
              delegate: delegate,
              child: Column(
                children: <Widget>[
                  Semantics(
                    label: 'label',
                    child: MarkSemanticsDirtySpy(
                      key: inner,
                      child: const Text('inner'),
                    ),
                  ),
                ],
              ),
            ),
          ),
        ),
      ),
    );

    final RenderMarkSemanticsDirtySpy innerObject = tester.renderObject<RenderMarkSemanticsDirtySpy>(find.byKey(inner));
    final RenderTestConfigDelegate objectWithDelegate = tester.renderObject<RenderTestConfigDelegate>(find.byType(TestConfigDelegate));
    final RenderMarkSemanticsDirtySpy boundaryParentObject = tester.renderObject<RenderMarkSemanticsDirtySpy>(find.byKey(boundaryParent));
    final RenderMarkSemanticsDirtySpy grandBoundaryParentObject = tester.renderObject<RenderMarkSemanticsDirtySpy>(find.byKey(grandBoundaryParent));
    void resetBuildState() {
      innerObject.hasRebuildSemantics = false;
      boundaryParentObject.hasRebuildSemantics = false;
      grandBoundaryParentObject.hasRebuildSemantics = false;
    }
    // Sanity check
    expect(innerObject.hasRebuildSemantics, isTrue);
    expect(boundaryParentObject.hasRebuildSemantics, isTrue);
    expect(grandBoundaryParentObject.hasRebuildSemantics, isTrue);
    resetBuildState();

    innerObject.markNeedsSemanticsUpdate();
    await tester.pump();
    // Inner boundary should not trigger rebuild above it.
    expect(innerObject.hasRebuildSemantics, isTrue);
    expect(boundaryParentObject.hasRebuildSemantics, isFalse);
    expect(grandBoundaryParentObject.hasRebuildSemantics, isFalse);
    resetBuildState();

    objectWithDelegate.markNeedsSemanticsUpdate();
    await tester.pump();
    // object with delegate rebuilds up to grand parent boundary;
    expect(innerObject.hasRebuildSemantics, isTrue);
    expect(boundaryParentObject.hasRebuildSemantics, isTrue);
    expect(grandBoundaryParentObject.hasRebuildSemantics, isTrue);
    resetBuildState();

    boundaryParentObject.markNeedsSemanticsUpdate();
    await tester.pump();
    // Render objects in between child delegate and grand boundary parent does
    // not mark the grand boundary parent dirty because it should not change the
    // generated sibling nodes.
    expect(innerObject.hasRebuildSemantics, isTrue);
    expect(boundaryParentObject.hasRebuildSemantics, isTrue);
    expect(grandBoundaryParentObject.hasRebuildSemantics, isFalse);
  });
}

class MarkSemanticsDirtySpy extends SingleChildRenderObjectWidget {
  const MarkSemanticsDirtySpy({super.key, super.child});
  @override
  RenderMarkSemanticsDirtySpy createRenderObject(BuildContext context) => RenderMarkSemanticsDirtySpy();
}

class RenderMarkSemanticsDirtySpy extends RenderProxyBox {
  RenderMarkSemanticsDirtySpy();
  bool hasRebuildSemantics = false;

  @override
  void describeSemanticsConfiguration(SemanticsConfiguration config) {
    config.isSemanticBoundary = true;
  }

  @override
  void assembleSemanticsNode(
    SemanticsNode node,
    SemanticsConfiguration config,
    Iterable<SemanticsNode> children,
  ) {
    hasRebuildSemantics = true;
  }
}

class TestConfigDelegate extends SingleChildRenderObjectWidget {
  const TestConfigDelegate({super.key, required this.delegate, super.child});
  final ChildSemanticsConfigurationsDelegate delegate;

  @override
  RenderTestConfigDelegate createRenderObject(BuildContext context) => RenderTestConfigDelegate(
    delegate: delegate,
  );

  @override
  void updateRenderObject(BuildContext context, RenderTestConfigDelegate renderObject) {
    renderObject.delegate = delegate;
  }
}

class RenderTestConfigDelegate extends RenderProxyBox {
  RenderTestConfigDelegate({
    ChildSemanticsConfigurationsDelegate? delegate,
  }) : _delegate = delegate;

  ChildSemanticsConfigurationsDelegate? get delegate => _delegate;
  ChildSemanticsConfigurationsDelegate? _delegate;
  set delegate(ChildSemanticsConfigurationsDelegate? value) {
    if (value != _delegate) {
      markNeedsSemanticsUpdate();
    }
    _delegate = value;
  }

  @override
  void describeSemanticsConfiguration(SemanticsConfiguration config) {
    config.childConfigurationsDelegate = _delegate;
  }
}
