// Copyright 2016 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 'dart:async';

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

import 'all_elements.dart';
import 'finders.dart';
import 'test_async_utils.dart';
import 'test_pointer.dart';

/// Class that programmatically interacts with widgets.
///
/// For a variant of this class suited specifically for unit tests, see [WidgetTester].
class WidgetController {
  /// Creates a widget controller that uses the given binding.
  WidgetController(this.binding);

  /// A reference to the current instance of the binding.
  final WidgetsBinding binding;

  // FINDER API

  // TODO(ianh): verify that the return values are of type T and throw
  // a good message otherwise, in all the generic methods below

  /// Checks if `finder` exists in the tree.
  bool any(Finder finder) {
    TestAsyncUtils.guardSync();
    return finder.evaluate().isNotEmpty;
  }


  /// All widgets currently in the widget tree (lazy pre-order traversal).
  ///
  /// Can contain duplicates, since widgets can be used in multiple
  /// places in the widget tree.
  Iterable<Widget> get allWidgets {
    TestAsyncUtils.guardSync();
    return allElements
           .map((Element element) => element.widget);
  }

  /// The matching widget in the widget tree.
  ///
  /// Throws a [StateError] if `finder` is empty or matches more than
  /// one widget.
  ///
  /// * Use [firstWidget] if you expect to match several widgets but only want the first.
  /// * Use [widgetList] if you expect to match several widgets and want all of them.
  Widget/*=T*/ widget/*<T extends Widget>*/(Finder finder) {
    TestAsyncUtils.guardSync();
    return finder.evaluate().single.widget;
  }

  /// The first matching widget according to a depth-first pre-order
  /// traversal of the widget tree.
  ///
  /// Throws a [StateError] if `finder` is empty.
  ///
  /// * Use [widget] if you only expect to match one widget.
  Widget/*=T*/ firstWidget/*<T extends Widget>*/(Finder finder) {
    TestAsyncUtils.guardSync();
    return finder.evaluate().first.widget;
  }

  /// The matching widgets in the widget tree.
  ///
  /// * Use [widget] if you only expect to match one widget.
  /// * Use [firstWidget] if you expect to match several but only want the first.
  Iterable<Widget/*=T*/> widgetList/*<T extends Widget>*/(Finder finder) {
    TestAsyncUtils.guardSync();
    return finder.evaluate().map((Element element) => element.widget);
  }


  /// All elements currently in the widget tree (lazy pre-order traversal).
  ///
  /// The returned iterable is lazy. It does not walk the entire widget tree
  /// immediately, but rather a chunk at a time as the iteration progresses
  /// using [Iterator.moveNext].
  Iterable<Element> get allElements {
    TestAsyncUtils.guardSync();
    return collectAllElementsFrom(binding.renderViewElement);
  }

  /// The matching element in the widget tree.
  ///
  /// Throws a [StateError] if `finder` is empty or matches more than
  /// one element.
  ///
  /// * Use [firstElement] if you expect to match several elements but only want the first.
  /// * Use [elementList] if you expect to match several elements and want all of them.
  Element/*=T*/ element/*<T extends Element>*/(Finder finder) {
    TestAsyncUtils.guardSync();
    return finder.evaluate().single;
  }

  /// The first matching element according to a depth-first pre-order
  /// traversal of the widget tree.
  ///
  /// Throws a [StateError] if `finder` is empty.
  ///
  /// * Use [element] if you only expect to match one element.
  Element/*=T*/ firstElement/*<T extends Element>*/(Finder finder) {
    TestAsyncUtils.guardSync();
    return finder.evaluate().first;
  }

  /// The matching elements in the widget tree.
  ///
  /// * Use [element] if you only expect to match one element.
  /// * Use [firstElement] if you expect to match several but only want the first.
  Iterable<Element/*=T*/> elementList/*<T extends Element>*/(Finder finder) {
    TestAsyncUtils.guardSync();
    return finder.evaluate();
  }


  /// All states currently in the widget tree (lazy pre-order traversal).
  ///
  /// The returned iterable is lazy. It does not walk the entire widget tree
  /// immediately, but rather a chunk at a time as the iteration progresses
  /// using [Iterator.moveNext].
  Iterable<State> get allStates {
    TestAsyncUtils.guardSync();
    return allElements
           .where((Element element) => element is StatefulElement)
           .map((StatefulElement element) => element.state);
  }

  /// The matching state in the widget tree.
  ///
  /// Throws a [StateError] if `finder` is empty, matches more than
  /// one state, or matches a widget that has no state.
  ///
  /// * Use [firstState] if you expect to match several states but only want the first.
  /// * Use [stateList] if you expect to match several states and want all of them.
  State/*=T*/ state/*<T extends State>*/(Finder finder) {
    TestAsyncUtils.guardSync();
    return _stateOf/*<T>*/(finder.evaluate().single, finder);
  }

  /// The first matching state according to a depth-first pre-order
  /// traversal of the widget tree.
  ///
  /// Throws a [StateError] if `finder` is empty or if the first
  /// matching widget has no state.
  ///
  /// * Use [state] if you only expect to match one state.
  State/*=T*/ firstState/*<T extends State>*/(Finder finder) {
    TestAsyncUtils.guardSync();
    return _stateOf/*<T>*/(finder.evaluate().first, finder);
  }

  /// The matching states in the widget tree.
  ///
  /// Throws a [StateError] if any of the elements in `finder` match a widget
  /// that has no state.
  ///
  /// * Use [state] if you only expect to match one state.
  /// * Use [firstState] if you expect to match several but only want the first.
  Iterable<State/*=T*/> stateList/*<T extends State>*/(Finder finder) {
    TestAsyncUtils.guardSync();
    return finder.evaluate().map((Element element) => _stateOf/*<T>*/(element, finder));
  }

  State/*=T*/ _stateOf/*<T extends State>*/(Element element, Finder finder) {
    TestAsyncUtils.guardSync();
    if (element is StatefulElement)
      return element.state;
    throw new StateError('Widget of type ${element.widget.runtimeType}, with ${finder.description}, is not a StatefulWidget.');
  }


  /// Render objects of all the widgets currently in the widget tree
  /// (lazy pre-order traversal).
  ///
  /// This will almost certainly include many duplicates since the
  /// render object of a [StatelessWidget] or [StatefulWidget] is the
  /// render object of its child; only [RenderObjectWidget]s have
  /// their own render object.
  Iterable<RenderObject> get allRenderObjects {
    TestAsyncUtils.guardSync();
    return allElements
           .map((Element element) => element.renderObject);
  }

  /// The render object of the matching widget in the widget tree.
  ///
  /// Throws a [StateError] if `finder` is empty or matches more than
  /// one widget (even if they all have the same render object).
  ///
  /// * Use [firstRenderObject] if you expect to match several render objects but only want the first.
  /// * Use [renderObjectList] if you expect to match several render objects and want all of them.
  RenderObject/*=T*/ renderObject/*<T extends RenderObject>*/(Finder finder) {
    TestAsyncUtils.guardSync();
    return finder.evaluate().single.renderObject;
  }

  /// The render object of the first matching widget according to a
  /// depth-first pre-order traversal of the widget tree.
  ///
  /// Throws a [StateError] if `finder` is empty.
  ///
  /// * Use [renderObject] if you only expect to match one render object.
  RenderObject/*=T*/ firstRenderObject/*<T extends RenderObject>*/(Finder finder) {
    TestAsyncUtils.guardSync();
    return finder.evaluate().first.renderObject;
  }

  /// The render objects of the matching widgets in the widget tree.
  ///
  /// * Use [renderObject] if you only expect to match one render object.
  /// * Use [firstRenderObject] if you expect to match several but only want the first.
  Iterable<RenderObject/*=T*/> renderObjectList/*<T extends RenderObject>*/(Finder finder) {
    TestAsyncUtils.guardSync();
    return finder.evaluate().map((Element element) => element.renderObject);
  }


  /// Returns a list of all the [Layer] objects in the rendering.
  List<Layer> get layers => _walkLayers(binding.renderView.layer).toList();
  Iterable<Layer> _walkLayers(Layer layer) sync* {
    TestAsyncUtils.guardSync();
    yield layer;
    if (layer is ContainerLayer) {
      ContainerLayer root = layer;
      Layer child = root.firstChild;
      while (child != null) {
        yield* _walkLayers(child);
        child = child.nextSibling;
      }
    }
  }


  // INTERACTION

  /// Dispatch a pointer down / pointer up sequence at the center of
  /// the given widget, assuming it is exposed. If the center of the
  /// widget is not exposed, this might send events to another
  /// object.
  Future<Null> tap(Finder finder, { int pointer: 1 }) {
    return tapAt(getCenter(finder), pointer: pointer);
  }

  /// Dispatch a pointer down / pointer up sequence at the given
  /// location.
  Future<Null> tapAt(Point location, { int pointer: 1 }) {
    return TestAsyncUtils.guard(() async {
      TestGesture gesture = await startGesture(location, pointer: pointer);
      await gesture.up();
      return null;
    });
  }

  /// Attempts a fling gesture starting from the center of the given
  /// widget, moving the given distance, reaching the given velocity.
  ///
  /// If the middle of the widget is not exposed, this might send
  /// events to another object.
  Future<Null> fling(Finder finder, Offset offset, double velocity, { int pointer: 1 }) {
    return flingFrom(getCenter(finder), offset, velocity, pointer: pointer);
  }

  /// Attempts a fling gesture starting from the given location,
  /// moving the given distance, reaching the given velocity.
  Future<Null> flingFrom(Point startLocation, Offset offset, double velocity, { int pointer: 1 }) {
    return TestAsyncUtils.guard(() async {
      assert(offset.distance > 0.0);
      assert(velocity != 0.0);   // velocity is pixels/second
      final TestPointer p = new TestPointer(pointer);
      final HitTestResult result = hitTestOnBinding(startLocation);
      const int kMoveCount = 50; // Needs to be >= kHistorySize, see _LeastSquaresVelocityTrackerStrategy
      final double timeStampDelta = 1000.0 * offset.distance / (kMoveCount * velocity);
      double timeStamp = 0.0;
      await sendEventToBinding(p.down(startLocation, timeStamp: new Duration(milliseconds: timeStamp.round())), result);
      for (int i = 0; i <= kMoveCount; i++) {
        final Point location = startLocation + Offset.lerp(Offset.zero, offset, i / kMoveCount);
        await sendEventToBinding(p.move(location, timeStamp: new Duration(milliseconds: timeStamp.round())), result);
        timeStamp += timeStampDelta;
      }
      await sendEventToBinding(p.up(timeStamp: new Duration(milliseconds: timeStamp.round())), result);
      return null;
    });
  }

  /// Attempts to drag the given widget by the given offset, by
  /// starting a drag in the middle of the widget.
  ///
  /// If the middle of the widget is not exposed, this might send
  /// events to another object.
  Future<Null> scroll(Finder finder, Offset offset, { int pointer: 1 }) {
    return scrollAt(getCenter(finder), offset, pointer: pointer);
  }

  /// Attempts a drag gesture consisting of a pointer down, a move by
  /// the given offset, and a pointer up.
  Future<Null> scrollAt(Point startLocation, Offset offset, { int pointer: 1 }) {
    return TestAsyncUtils.guard(() async {
      TestGesture gesture = await startGesture(startLocation, pointer: pointer);
      await gesture.moveBy(offset);
      await gesture.up();
      return null;
    });
  }

  /// Begins a gesture at a particular point, and returns the
  /// [TestGesture] object which you can use to continue the gesture.
  Future<TestGesture> startGesture(Point downLocation, { int pointer: 1 }) {
    return TestGesture.down(downLocation, pointer: pointer, hitTester: hitTestOnBinding, dispatcher: sendEventToBinding);
  }

  /// Forwards the given location to the binding's hitTest logic.
  HitTestResult hitTestOnBinding(Point location) {
    final HitTestResult result = new HitTestResult();
    binding.hitTest(result, location);
    return result;
  }

  /// Forwards the given pointer event to the binding.
  Future<Null> sendEventToBinding(PointerEvent event, HitTestResult result) {
    return TestAsyncUtils.guard(() async {
      binding.dispatchEvent(event, result);
      return null;
    });
  }


  // GEOMETRY

  /// Returns the point at the center of the given widget.
  Point getCenter(Finder finder) {
    return _getElementPoint(finder, (Size size) => size.center(Point.origin));
  }

  /// Returns the point at the top left of the given widget.
  Point getTopLeft(Finder finder) {
    return _getElementPoint(finder, (Size size) => Point.origin);
  }

  /// Returns the point at the top right of the given widget. This
  /// point is not inside the object's hit test area.
  Point getTopRight(Finder finder) {
    return _getElementPoint(finder, (Size size) => size.topRight(Point.origin));
  }

  /// Returns the point at the bottom left of the given widget. This
  /// point is not inside the object's hit test area.
  Point getBottomLeft(Finder finder) {
    return _getElementPoint(finder, (Size size) => size.bottomLeft(Point.origin));
  }

  /// Returns the point at the bottom right of the given widget. This
  /// point is not inside the object's hit test area.
  Point getBottomRight(Finder finder) {
    return _getElementPoint(finder, (Size size) => size.bottomRight(Point.origin));
  }

  Point _getElementPoint(Finder finder, Point sizeToPoint(Size size)) {
    TestAsyncUtils.guardSync();
    Element element = finder.evaluate().single;
    RenderBox box = element.renderObject;
    assert(box != null);
    return box.localToGlobal(sizeToPoint(box.size));
  }

  /// Returns the size of the given widget. This is only valid once
  /// the widget's render object has been laid out at least once.
  Size getSize(Finder finder) {
    TestAsyncUtils.guardSync();
    Element element = finder.evaluate().single;
    RenderBox box = element.renderObject;
    assert(box != null);
    return box.size;
  }
}
