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

import 'test_widgets.dart';

class TestScrollPosition extends ScrollPosition {
  TestScrollPosition(
    this.extentMultiplier,
    Scrollable2State state,
    Tolerance scrollTolerances,
    ScrollPosition oldPosition,
  ) : _pixels = 100.0, super(state, scrollTolerances, oldPosition);

  final double extentMultiplier;

  double _min, _viewport, _max, _pixels;

  @override
  double get pixels => _pixels;

  @override
  double setPixels(double value) {
    double oldPixels = _pixels;
    _pixels = value;
    dispatchNotification(activity.createScrollUpdateNotification(state, _pixels - oldPixels));
    return 0.0;
  }

  @override
  void correctBy(double correction) {
    _pixels += correction;
  }

  @override
  void applyViewportDimension(double viewportDimension) {
    _viewport = viewportDimension;
    super.applyViewportDimension(viewportDimension);
  }

  @override
  bool applyContentDimensions(double minScrollExtent, double maxScrollExtent) {
    _min = minScrollExtent;
    _max = maxScrollExtent;
    return super.applyContentDimensions(minScrollExtent, maxScrollExtent);
  }

  @override
  ScrollableMetrics getMetrics() {
    double insideExtent = _viewport;
    double beforeExtent = _pixels - _min;
    double afterExtent = _max - _pixels;
    if (insideExtent > 0.0) {
      return new ScrollableMetrics(
        extentBefore: extentMultiplier * beforeExtent / insideExtent,
        extentInside: extentMultiplier,
        extentAfter: extentMultiplier * afterExtent / insideExtent,
      );
    } else {
      return new ScrollableMetrics(
        extentBefore: 0.0,
        extentInside: 0.0,
        extentAfter: 0.0,
      );
    }
  }
}

class TestScrollBehavior extends ScrollBehavior2 {
  TestScrollBehavior(this.extentMultiplier);
  final double extentMultiplier;

  @override
  Widget wrap(BuildContext context, Widget child, AxisDirection axisDirection) => child;

  @override
  ScrollPosition createScrollPosition(BuildContext context, Scrollable2State state, ScrollPosition oldPosition, ScrollPhysics physics) {
    return new TestScrollPosition(extentMultiplier, state, ViewportScrollBehavior.defaultScrollTolerances, oldPosition);
  }

  @override
  bool shouldNotify(TestScrollBehavior oldDelegate) {
    return extentMultiplier != oldDelegate.extentMultiplier;
  }
}

void main() {
  testWidgets('Changing the scroll behavior dynamically', (WidgetTester tester) async {
    await tester.pumpWidget(new TestScrollable(
      scrollBehavior: new TestScrollBehavior(1.0),
      slivers: <Widget>[
        new SliverToBoxAdapter(child: new SizedBox(height: 2000.0)),
      ],
    ));
    Scrollable2State state = tester.state(find.byType(Scrollable2));

    expect(state.position.getMetrics().extentInside, 1.0);
    await tester.pumpWidget(new TestScrollable(
      scrollBehavior: new TestScrollBehavior(2.0),
      slivers: <Widget>[
        new SliverToBoxAdapter(child: new SizedBox(height: 2000.0)),
      ],
    ));
    expect(state.position.getMetrics().extentInside, 2.0);
  });
}