// 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:math' as math;

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

void verifyPaintPosition(GlobalKey key, Offset ideal) {
  final RenderObject target = key.currentContext.findRenderObject();
  expect(target.parent, isA<RenderViewport>());
  final SliverPhysicalParentData parentData = target.parentData as SliverPhysicalParentData;
  final Offset actual = parentData.paintOffset;
  expect(actual, ideal);
}

void main() {
  testWidgets('Sliver protocol', (WidgetTester tester) async {
    GlobalKey key1, key2, key3, key4, key5;
    await tester.pumpWidget(
      Directionality(
        textDirection: TextDirection.ltr,
        child: CustomScrollView(
          slivers: <Widget>[
            BigSliver(key: key1 = GlobalKey()),
            OverlappingSliver(key: key2 = GlobalKey()),
            OverlappingSliver(key: key3 = GlobalKey()),
            BigSliver(key: key4 = GlobalKey()),
            BigSliver(key: key5 = GlobalKey()),
          ],
        ),
      ),
    );
    final ScrollPosition position = tester.state<ScrollableState>(find.byType(Scrollable)).position;
    const double max = RenderBigSliver.height * 3.0 + (RenderOverlappingSliver.totalHeight) * 2.0 - 600.0; // 600 is the height of the test viewport
    assert(max < 10000.0);
    expect(max, 1450.0);
    expect(position.pixels, 0.0);
    expect(position.minScrollExtent, 0.0);
    expect(position.maxScrollExtent, max);
    position.animateTo(10000.0, curve: Curves.linear, duration: const Duration(minutes: 1));
    await tester.pumpAndSettle(const Duration(milliseconds: 10));
    expect(position.pixels, max);
    expect(position.minScrollExtent, 0.0);
    expect(position.maxScrollExtent, max);
    verifyPaintPosition(key1, const Offset(0.0, 0.0));
    verifyPaintPosition(key2, const Offset(0.0, 0.0));
    verifyPaintPosition(key3, const Offset(0.0, 0.0));
    verifyPaintPosition(key4, const Offset(0.0, 0.0));
    verifyPaintPosition(key5, const Offset(0.0, 50.0));
  });
}

class RenderBigSliver extends RenderSliver {
  static const double height = 550.0;
  double get paintExtent => (height - constraints.scrollOffset).clamp(0.0, constraints.remainingPaintExtent) as double;

  @override
  void performLayout() {
    geometry = SliverGeometry(
      scrollExtent: height,
      paintExtent: paintExtent,
      maxPaintExtent: height,
    );
  }
}

class BigSliver extends LeafRenderObjectWidget {
  const BigSliver({ Key key }) : super(key: key);
  @override
  RenderBigSliver createRenderObject(BuildContext context) {
    return RenderBigSliver();
  }
}

class RenderOverlappingSliver extends RenderSliver {
  static const double totalHeight = 200.0;
  static const double fixedHeight = 100.0;

  double get paintExtent {
    return math.min(
             math.max(
               fixedHeight,
               totalHeight - constraints.scrollOffset,
             ),
             constraints.remainingPaintExtent,
           );
  }

  double get layoutExtent {
    return (totalHeight - constraints.scrollOffset).clamp(0.0, constraints.remainingPaintExtent) as double;
  }

  @override
  void performLayout() {
    geometry = SliverGeometry(
      scrollExtent: totalHeight,
      paintExtent: paintExtent,
      layoutExtent: layoutExtent,
      maxPaintExtent: totalHeight,
    );
  }
}

class OverlappingSliver extends LeafRenderObjectWidget {
  const OverlappingSliver({ Key key }) : super(key: key);
  @override
  RenderOverlappingSliver createRenderObject(BuildContext context) {
    return RenderOverlappingSliver();
  }
}
