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

void main() {
  testWidgets('!pinned && !floating && !bottom ==> fade opacity', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    await tester.pumpWidget(
        _TestWidget(
          pinned: false,
          floating: false,
          bottom: false,
          controller: controller,
        ),
    );

    final RenderParagraph render = tester.renderObject(find.text('Hallo Welt!!1'));
    expect(render.text.style.color.opacity, 1.0);

    controller.jumpTo(200.0);
    await tester.pumpAndSettle();
    expect(render.text.style.color.opacity, 0.0);
  });

  testWidgets('!pinned && !floating && bottom ==> fade opacity', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    await tester.pumpWidget(
        _TestWidget(
          pinned: false,
          floating: false,
          bottom: true,
          controller: controller,
        ),
    );

    final RenderParagraph render = tester.renderObject(find.text('Hallo Welt!!1'));
    expect(render.text.style.color.opacity, 1.0);

    controller.jumpTo(200.0);
    await tester.pumpAndSettle();
    expect(render.text.style.color.opacity, 0.0);
  });

  testWidgets('!pinned && floating && !bottom ==> fade opacity', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    await tester.pumpWidget(
        _TestWidget(
          pinned: false,
          floating: true,
          bottom: false,
          controller: controller,
        ),
    );

    final RenderParagraph render = tester.renderObject(find.text('Hallo Welt!!1'));
    expect(render.text.style.color.opacity, 1.0);

    controller.jumpTo(200.0);
    await tester.pumpAndSettle();
    expect(render.text.style.color.opacity, 0.0);
  });

  testWidgets('!pinned && floating && bottom ==> fade opacity', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    await tester.pumpWidget(
        _TestWidget(
          pinned: false,
          floating: true,
          bottom: true,
          controller: controller,
        ),
    );

    final RenderParagraph render = tester.renderObject(find.text('Hallo Welt!!1'));
    expect(render.text.style.color.opacity, 1.0);

    controller.jumpTo(200.0);
    await tester.pumpAndSettle();
    expect(render.text.style.color.opacity, 0.0);
  });

  testWidgets('pinned && !floating && !bottom ==> 1.0 opacity', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    await tester.pumpWidget(
        _TestWidget(
          pinned: true,
          floating: false,
          bottom: false,
          controller: controller,
        ),
    );

    final RenderParagraph render = tester.renderObject(find.text('Hallo Welt!!1'));
    expect(render.text.style.color.opacity, 1.0);

    controller.jumpTo(200.0);
    await tester.pumpAndSettle();
    expect(render.text.style.color.opacity, 1.0);
  });

  testWidgets('pinned && !floating && bottom ==> 1.0 opacity', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    await tester.pumpWidget(
        _TestWidget(
          pinned: true,
          floating: false,
          bottom: true,
          controller: controller,
        ),
    );

    final RenderParagraph render = tester.renderObject(find.text('Hallo Welt!!1'));
    expect(render.text.style.color.opacity, 1.0);

    controller.jumpTo(200.0);
    await tester.pumpAndSettle();
    expect(render.text.style.color.opacity, 1.0);
  });

  testWidgets('pinned && floating && !bottom ==> 1.0 opacity', (WidgetTester tester) async {
    // Regression test for https://github.com/flutter/flutter/issues/25000.

    final ScrollController controller = ScrollController();
    await tester.pumpWidget(
        _TestWidget(
          pinned: true,
          floating: true,
          bottom: false,
          controller: controller,
        ),
    );

    final RenderParagraph render = tester.renderObject(find.text('Hallo Welt!!1'));
    expect(render.text.style.color.opacity, 1.0);

    controller.jumpTo(200.0);
    await tester.pumpAndSettle();
    expect(render.text.style.color.opacity, 1.0);
  });

  testWidgets('pinned && floating && bottom && extraToolbarHeight == 0.0 ==> fade opacity', (WidgetTester tester) async {
    // Regression test for https://github.com/flutter/flutter/issues/25993.

    final ScrollController controller = ScrollController();
    await tester.pumpWidget(
      _TestWidget(
        pinned: true,
        floating: true,
        bottom: true,
        controller: controller,
      ),
    );

    final RenderParagraph render = tester.renderObject(find.text('Hallo Welt!!1'));
    expect(render.text.style.color.opacity, 1.0);

    controller.jumpTo(200.0);
    await tester.pumpAndSettle();
    expect(render.text.style.color.opacity, 0.0);
  });

  testWidgets('pinned && floating && bottom && extraToolbarHeight != 0.0 ==> 1.0 opacity', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    await tester.pumpWidget(
      _TestWidget(
        pinned: true,
        floating: true,
        bottom: true,
        collapsedHeight: 100.0,
        controller: controller,
      ),
    );

    final RenderParagraph render = tester.renderObject(find.text('Hallo Welt!!1'));
    expect(render.text.style.color.opacity, 1.0);

    controller.jumpTo(200.0);
    await tester.pumpAndSettle();
    expect(render.text.style.color.opacity, 1.0);
  });

  testWidgets('!pinned && !floating && !bottom && extraToolbarHeight != 0.0 ==> fade opacity', (WidgetTester tester) async {
    final ScrollController controller = ScrollController();
    const double collapsedHeight = 100.0;
    await tester.pumpWidget(
        _TestWidget(
          pinned: false,
          floating: false,
          bottom: false,
          controller: controller,
          collapsedHeight: collapsedHeight,
        ),
    );

    final RenderParagraph render = tester.renderObject(find.text('Hallo Welt!!1'));
    expect(render.text.style.color.opacity, 1.0);

    controller.jumpTo(collapsedHeight);
    await tester.pumpAndSettle();
    expect(render.text.style.color.opacity, 0.0);
  });
}

class _TestWidget extends StatelessWidget {

  const _TestWidget({
    this.pinned,
    this.floating,
    this.bottom,
    this.controller,
    this.collapsedHeight,
  });

  final bool pinned;
  final bool floating;
  final bool bottom;
  final ScrollController controller;
  final double collapsedHeight;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: CustomScrollView(
        controller: controller,
        slivers: <Widget>[
          SliverAppBar(
            pinned: pinned,
            floating: floating,
            expandedHeight: 120.0,
            collapsedHeight: collapsedHeight,
            title: const Text('Hallo Welt!!1'),
            bottom: !bottom ? null :  PreferredSize(
              preferredSize: const Size.fromHeight(35.0),
              child: Container(),
            ),
          ),
          SliverList(
            delegate: SliverChildListDelegate(List<Widget>.generate(20, (int i) {
              return Container(
                child: Text('Tile $i'),
                height: 100.0,
              );
            })),
          ),
        ],
      ),
    );
  }

}
