// 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_test/flutter_test.dart';

import 'rendering_tester.dart';

void main() {
  TestRenderingFlutterBinding.ensureInitialized();

  test('RenderSliverFixedExtentList layout test - rounding error', () {
    final List<RenderBox> children = <RenderBox>[
      RenderSizedBox(const Size(400.0, 100.0)),
      RenderSizedBox(const Size(400.0, 100.0)),
      RenderSizedBox(const Size(400.0, 100.0)),
    ];
    final TestRenderSliverBoxChildManager childManager = TestRenderSliverBoxChildManager(
      children: children,
    );
    final RenderViewport root = RenderViewport(
      crossAxisDirection: AxisDirection.right,
      offset: ViewportOffset.zero(),
      cacheExtent: 0,
      children: <RenderSliver>[
        childManager.createRenderSliverFillViewport(),
      ],
    );
    layout(root);
    expect(children[0].attached, true);
    expect(children[1].attached, false);

    root.offset = ViewportOffset.fixed(600);
    pumpFrame();
    expect(children[0].attached, false);
    expect(children[1].attached, true);

    // Simulate double precision error.
    root.offset = ViewportOffset.fixed(1199.999999999998);
    pumpFrame();
    expect(children[1].attached, false);
    expect(children[2].attached, true);
  });

  group('getMaxChildIndexForScrollOffset', () {
    // Regression test for https://github.com/flutter/flutter/issues/68182

    const double genericItemExtent = 600.0;
    const double extraValueToNotHaveRoundingIssues = 1e-10;
    const double extraValueToHaveRoundingIssues = 1e-11;

    test('should be 0 when item extent is 0', () {
      const double offsetValueWhichDoesntCare = 1234;
      final int actual = testGetMaxChildIndexForScrollOffset(offsetValueWhichDoesntCare, 0);
      expect(actual, 0);
    });

    test('should be 0 when offset is 0', () {
      final int actual = testGetMaxChildIndexForScrollOffset(0, genericItemExtent);
      expect(actual, 0);
    });

    test('should be 0 when offset is equal to item extent', () {
      final int actual = testGetMaxChildIndexForScrollOffset(genericItemExtent, genericItemExtent);
      expect(actual, 0);
    });

    test('should be 1 when offset is greater than item extent', () {
      final int actual = testGetMaxChildIndexForScrollOffset(genericItemExtent + 1, genericItemExtent);
      expect(actual, 1);
    });

    test('should be 1 when offset is slightly greater than item extent', () {
      final int actual = testGetMaxChildIndexForScrollOffset(
        genericItemExtent + extraValueToNotHaveRoundingIssues,
        genericItemExtent,
      );
      expect(actual, 1);
    });

    test('should be 4 when offset is four times and a half greater than item extent', () {
      final int actual = testGetMaxChildIndexForScrollOffset(genericItemExtent * 4.5, genericItemExtent);
      expect(actual, 4);
    });

    test('should be 5 when offset is 6 times greater than item extent', () {
      const double anotherGenericItemExtent = 414.0;
      final int actual = testGetMaxChildIndexForScrollOffset(
        anotherGenericItemExtent * 6,
        anotherGenericItemExtent,
      );
      expect(actual, 5);
    });

    test('should be 5 when offset is 6 times greater than a specific item extent where the division will return more than 13 zero decimals', () {
      const double itemExtentSpecificForAProblematicScreenSize = 411.42857142857144;
      final int actual = testGetMaxChildIndexForScrollOffset(
        itemExtentSpecificForAProblematicScreenSize * 6 + extraValueToHaveRoundingIssues,
        itemExtentSpecificForAProblematicScreenSize,
      );
      expect(actual, 5);
    });

    test('should be 0 when offset is a bit greater than item extent', () {
      final int actual = testGetMaxChildIndexForScrollOffset(
        genericItemExtent + extraValueToHaveRoundingIssues,
        genericItemExtent,
      );
      expect(actual, 0);
    });
  });

  test('Implements paintsChild correctly', () {
    final List<RenderBox> children = <RenderBox>[
      RenderSizedBox(const Size(400.0, 100.0)),
      RenderSizedBox(const Size(400.0, 100.0)),
      RenderSizedBox(const Size(400.0, 100.0)),
    ];
    final TestRenderSliverBoxChildManager childManager = TestRenderSliverBoxChildManager(
      children: children,
    );
    final RenderViewport root = RenderViewport(
      crossAxisDirection: AxisDirection.right,
      offset: ViewportOffset.zero(),
      cacheExtent: 0,
      children: <RenderSliver>[
        childManager.createRenderSliverFillViewport(),
      ],
    );
    layout(root);
    expect(children.first.parent, isA<RenderSliverMultiBoxAdaptor>());

    final RenderSliverMultiBoxAdaptor parent = children.first.parent! as RenderSliverMultiBoxAdaptor;
    expect(parent.paintsChild(children[0]), true);
    expect(parent.paintsChild(children[1]), false);
    expect(parent.paintsChild(children[2]), false);

    root.offset = ViewportOffset.fixed(600);
    pumpFrame();
    expect(parent.paintsChild(children[0]), false);
    expect(parent.paintsChild(children[1]), true);
    expect(parent.paintsChild(children[2]), false);

    root.offset = ViewportOffset.fixed(1200);
    pumpFrame();
    expect(parent.paintsChild(children[0]), false);
    expect(parent.paintsChild(children[1]), false);
    expect(parent.paintsChild(children[2]), true);
  });
}

int testGetMaxChildIndexForScrollOffset(double scrollOffset, double itemExtent) {
  final TestRenderSliverFixedExtentBoxAdaptor renderSliver = TestRenderSliverFixedExtentBoxAdaptor();
  return renderSliver.getMaxChildIndexForScrollOffset(scrollOffset, itemExtent);
}

class TestRenderSliverBoxChildManager extends RenderSliverBoxChildManager {
  TestRenderSliverBoxChildManager({
    required this.children,
  });

  RenderSliverMultiBoxAdaptor? _renderObject;
  List<RenderBox> children;

  RenderSliverFillViewport createRenderSliverFillViewport() {
    assert(_renderObject == null);
    _renderObject = RenderSliverFillViewport(
      childManager: this,
    );
    return _renderObject! as RenderSliverFillViewport;
  }

  int? _currentlyUpdatingChildIndex;

  @override
  void createChild(int index, { required RenderBox? after }) {
    if (index < 0 || index >= children.length) {
      return;
    }
    try {
      _currentlyUpdatingChildIndex = index;
      _renderObject!.insert(children[index], after: after);
    } finally {
      _currentlyUpdatingChildIndex = null;
    }
  }

  @override
  void removeChild(RenderBox child) {
    _renderObject!.remove(child);
  }

  @override
  double estimateMaxScrollOffset(
    SliverConstraints constraints, {
    int? firstIndex,
    int? lastIndex,
    double? leadingScrollOffset,
    double? trailingScrollOffset,
  }) {
    assert(lastIndex! >= firstIndex!);
    return children.length * (trailingScrollOffset! - leadingScrollOffset!) / (lastIndex! - firstIndex! + 1);
  }

  @override
  int get childCount => children.length;

  @override
  void didAdoptChild(RenderBox child) {
    assert(_currentlyUpdatingChildIndex != null);
    final SliverMultiBoxAdaptorParentData childParentData = child.parentData! as SliverMultiBoxAdaptorParentData;
    childParentData.index = _currentlyUpdatingChildIndex;
  }

  @override
  void setDidUnderflow(bool value) { }
}

class TestRenderSliverFixedExtentBoxAdaptor extends RenderSliverFixedExtentBoxAdaptor {
  TestRenderSliverFixedExtentBoxAdaptor()
    :super(childManager: TestRenderSliverBoxChildManager(children: <RenderBox>[]));

  @override
  int getMaxChildIndexForScrollOffset(double scrollOffset, double itemExtent) {
    return super.getMaxChildIndexForScrollOffset(scrollOffset, itemExtent);
  }

  @override
  double get itemExtent => throw UnimplementedError();
}
