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

enum _DragTarget {
  start,
  end
}

// How close a drag's start position must be to the target point. This is
// a distance squared.
const double _kTargetSlop = 2500.0;

// Used by the Painter classes.
const double _kPointRadius = 6.0;

class _DragHandler extends Drag {
  _DragHandler(this.onUpdate, this.onCancel, this.onEnd);

  final GestureDragUpdateCallback onUpdate;
  final GestureDragCancelCallback onCancel;
  final GestureDragEndCallback onEnd;

  @override
  void update(DragUpdateDetails details) {
    onUpdate(details);
  }

  @override
  void cancel() {
    onCancel();
  }

  @override
  void end(DragEndDetails details) {
    onEnd(details);
  }
}

class _IgnoreDrag extends Drag {
}

class _PointDemoPainter extends CustomPainter {
  _PointDemoPainter({
    Animation<double> repaint,
    this.arc,
  }) : _repaint = repaint, super(repaint: repaint);

  final MaterialPointArcTween arc;
  final Animation<double> _repaint;

  void drawPoint(Canvas canvas, Offset point, Color color) {
    final Paint paint = Paint()
      ..color = color.withOpacity(0.25)
      ..style = PaintingStyle.fill;
    canvas.drawCircle(point, _kPointRadius, paint);
    paint
      ..color = color
      ..style = PaintingStyle.stroke
      ..strokeWidth = 2.0;
    canvas.drawCircle(point, _kPointRadius + 1.0, paint);
  }

  @override
  void paint(Canvas canvas, Size size) {
    final Paint paint = Paint();

    if (arc.center != null)
      drawPoint(canvas, arc.center, Colors.grey.shade400);

    paint
      ..isAntiAlias = false // Work-around for github.com/flutter/flutter/issues/5720
      ..color = Colors.green.withOpacity(0.25)
      ..strokeWidth = 4.0
      ..style = PaintingStyle.stroke;
    if (arc.center != null && arc.radius != null)
      canvas.drawCircle(arc.center, arc.radius, paint);
    else
      canvas.drawLine(arc.begin, arc.end, paint);

    drawPoint(canvas, arc.begin, Colors.green);
    drawPoint(canvas, arc.end, Colors.red);

    paint
      ..color = Colors.green
      ..style = PaintingStyle.fill;
    canvas.drawCircle(arc.lerp(_repaint.value), _kPointRadius, paint);
  }

  @override
  bool hitTest(Offset position) {
    return (arc.begin - position).distanceSquared < _kTargetSlop
        || (arc.end - position).distanceSquared < _kTargetSlop;
  }

  @override
  bool shouldRepaint(_PointDemoPainter oldPainter) => arc != oldPainter.arc;
}

class _PointDemo extends StatefulWidget {
  const _PointDemo({ Key key, this.controller }) : super(key: key);

  final AnimationController controller;

  @override
  _PointDemoState createState() => _PointDemoState();
}

class _PointDemoState extends State<_PointDemo> {
  final GlobalKey _painterKey = GlobalKey();

  CurvedAnimation _animation;
  _DragTarget _dragTarget;
  Size _screenSize;
  Offset _begin;
  Offset _end;

  @override
  void initState() {
    super.initState();
    _animation = CurvedAnimation(parent: widget.controller, curve: Curves.fastOutSlowIn);
  }

  @override
  void dispose() {
    widget.controller.value = 0.0;
    super.dispose();
  }

  Drag _handleOnStart(Offset position) {
    // TODO(hansmuller): allow the user to drag both points at the same time.
    if (_dragTarget != null)
      return _IgnoreDrag();

    final RenderBox box = _painterKey.currentContext.findRenderObject();
    final double startOffset = (box.localToGlobal(_begin) - position).distanceSquared;
    final double endOffset = (box.localToGlobal(_end) - position).distanceSquared;
    setState(() {
      if (startOffset < endOffset && startOffset < _kTargetSlop)
        _dragTarget = _DragTarget.start;
      else if (endOffset < _kTargetSlop)
        _dragTarget = _DragTarget.end;
      else
        _dragTarget = null;
    });

    return _DragHandler(_handleDragUpdate, _handleDragCancel, _handleDragEnd);
  }

  void _handleDragUpdate(DragUpdateDetails details) {
    switch (_dragTarget) {
      case _DragTarget.start:
        setState(() {
          _begin = _begin + details.delta;
        });
        break;
      case _DragTarget.end:
        setState(() {
          _end = _end + details.delta;
        });
        break;
    }
  }

  void _handleDragCancel() {
    _dragTarget = null;
    widget.controller.value = 0.0;
  }

  void _handleDragEnd(DragEndDetails details) {
    _dragTarget = null;
  }

  @override
  Widget build(BuildContext context) {
    final Size screenSize = MediaQuery.of(context).size;
    if (_screenSize == null || _screenSize != screenSize) {
      _screenSize = screenSize;
      _begin = Offset(screenSize.width * 0.5, screenSize.height * 0.2);
      _end = Offset(screenSize.width * 0.1, screenSize.height * 0.4);
    }

    final MaterialPointArcTween arc = MaterialPointArcTween(begin: _begin, end: _end);
    return RawGestureDetector(
      behavior: _dragTarget == null ? HitTestBehavior.deferToChild : HitTestBehavior.opaque,
      gestures: <Type, GestureRecognizerFactory>{
        ImmediateMultiDragGestureRecognizer: GestureRecognizerFactoryWithHandlers<ImmediateMultiDragGestureRecognizer>(
          () => ImmediateMultiDragGestureRecognizer(),
          (ImmediateMultiDragGestureRecognizer instance) {
            instance
              ..onStart = _handleOnStart;
          },
        ),
      },
      child: ClipRect(
        child: CustomPaint(
          key: _painterKey,
          foregroundPainter: _PointDemoPainter(
            repaint: _animation,
            arc: arc,
          ),
          // Watch out: if this IgnorePointer is left out, then gestures that
          // fail _PointDemoPainter.hitTest() will still be recognized because
          // they do overlap this child, which is as big as the CustomPaint.
          child: IgnorePointer(
            child: Padding(
              padding: const EdgeInsets.all(16.0),
              child: Text(
                'Tap the refresh button to run the animation. Drag the green '
                "and red points to change the animation's path.",
                style: Theme.of(context).textTheme.caption.copyWith(fontSize: 16.0),
              ),
            ),
          ),
        ),
      ),
    );
  }
}

class _RectangleDemoPainter extends CustomPainter {
  _RectangleDemoPainter({
    Animation<double> repaint,
    this.arc,
  }) : _repaint = repaint, super(repaint: repaint);

  final MaterialRectArcTween arc;
  final Animation<double> _repaint;

  void drawPoint(Canvas canvas, Offset p, Color color) {
    final Paint paint = Paint()
      ..color = color.withOpacity(0.25)
      ..style = PaintingStyle.fill;
    canvas.drawCircle(p, _kPointRadius, paint);
    paint
      ..color = color
      ..style = PaintingStyle.stroke
      ..strokeWidth = 2.0;
    canvas.drawCircle(p, _kPointRadius + 1.0, paint);
  }

  void drawRect(Canvas canvas, Rect rect, Color color) {
    final Paint paint = Paint()
      ..color = color.withOpacity(0.25)
      ..strokeWidth = 4.0
      ..style = PaintingStyle.stroke;
    canvas.drawRect(rect, paint);
    drawPoint(canvas, rect.center, color);
  }

  @override
  void paint(Canvas canvas, Size size) {
    drawRect(canvas, arc.begin, Colors.green);
    drawRect(canvas, arc.end, Colors.red);
    drawRect(canvas, arc.lerp(_repaint.value), Colors.blue);
  }

  @override
  bool hitTest(Offset position) {
    return (arc.begin.center - position).distanceSquared < _kTargetSlop
        || (arc.end.center - position).distanceSquared < _kTargetSlop;
  }

  @override
  bool shouldRepaint(_RectangleDemoPainter oldPainter) => arc != oldPainter.arc;
}

class _RectangleDemo extends StatefulWidget {
  const _RectangleDemo({ Key key, this.controller }) : super(key: key);

  final AnimationController controller;

  @override
  _RectangleDemoState createState() => _RectangleDemoState();
}

class _RectangleDemoState extends State<_RectangleDemo> {
  final GlobalKey _painterKey = GlobalKey();

  CurvedAnimation _animation;
  _DragTarget _dragTarget;
  Size _screenSize;
  Rect _begin;
  Rect _end;

  @override
  void initState() {
    super.initState();
    _animation = CurvedAnimation(parent: widget.controller, curve: Curves.fastOutSlowIn);
  }

  @override
  void dispose() {
    widget.controller.value = 0.0;
    super.dispose();
  }

  Drag _handleOnStart(Offset position) {
    // TODO(hansmuller): allow the user to drag both points at the same time.
    if (_dragTarget != null)
      return _IgnoreDrag();

    final RenderBox box = _painterKey.currentContext.findRenderObject();
    final double startOffset = (box.localToGlobal(_begin.center) - position).distanceSquared;
    final double endOffset = (box.localToGlobal(_end.center) - position).distanceSquared;
    setState(() {
      if (startOffset < endOffset && startOffset < _kTargetSlop)
        _dragTarget = _DragTarget.start;
      else if (endOffset < _kTargetSlop)
        _dragTarget = _DragTarget.end;
      else
        _dragTarget = null;
    });
    return _DragHandler(_handleDragUpdate, _handleDragCancel, _handleDragEnd);
  }

  void _handleDragUpdate(DragUpdateDetails details) {
    switch (_dragTarget) {
      case _DragTarget.start:
        setState(() {
          _begin = _begin.shift(details.delta);
        });
        break;
      case _DragTarget.end:
        setState(() {
          _end = _end.shift(details.delta);
        });
        break;
    }
  }

  void _handleDragCancel() {
    _dragTarget = null;
    widget.controller.value = 0.0;
  }

  void _handleDragEnd(DragEndDetails details) {
    _dragTarget = null;
  }

  @override
  Widget build(BuildContext context) {
    final Size screenSize = MediaQuery.of(context).size;
    if (_screenSize == null || _screenSize != screenSize) {
      _screenSize = screenSize;
      _begin = Rect.fromLTWH(
        screenSize.width * 0.5, screenSize.height * 0.2,
        screenSize.width * 0.4, screenSize.height * 0.2,
      );
      _end = Rect.fromLTWH(
        screenSize.width * 0.1, screenSize.height * 0.4,
        screenSize.width * 0.3, screenSize.height * 0.3,
      );
    }

    final MaterialRectArcTween arc = MaterialRectArcTween(begin: _begin, end: _end);
    return RawGestureDetector(
      behavior: _dragTarget == null ? HitTestBehavior.deferToChild : HitTestBehavior.opaque,
      gestures: <Type, GestureRecognizerFactory>{
        ImmediateMultiDragGestureRecognizer: GestureRecognizerFactoryWithHandlers<ImmediateMultiDragGestureRecognizer>(
          () => ImmediateMultiDragGestureRecognizer(),
          (ImmediateMultiDragGestureRecognizer instance) {
            instance
              ..onStart = _handleOnStart;
          },
        ),
      },
      child: ClipRect(
        child: CustomPaint(
          key: _painterKey,
          foregroundPainter: _RectangleDemoPainter(
            repaint: _animation,
            arc: arc,
          ),
          // Watch out: if this IgnorePointer is left out, then gestures that
          // fail _RectDemoPainter.hitTest() will still be recognized because
          // they do overlap this child, which is as big as the CustomPaint.
          child: IgnorePointer(
            child: Padding(
              padding: const EdgeInsets.all(16.0),
              child: Text(
                'Tap the refresh button to run the animation. Drag the rectangles '
                "to change the animation's path.",
                style: Theme.of(context).textTheme.caption.copyWith(fontSize: 16.0),
              ),
            ),
          ),
        ),
      ),
    );
  }
}

typedef _DemoBuilder = Widget Function(_ArcDemo demo);

class _ArcDemo {
  _ArcDemo(this.title, this.builder, TickerProvider vsync)
    : controller = AnimationController(duration: const Duration(milliseconds: 500), vsync: vsync),
      key = GlobalKey(debugLabel: title);

  final String title;
  final _DemoBuilder builder;
  final AnimationController controller;
  final GlobalKey key;
}

class AnimationDemo extends StatefulWidget {
  const AnimationDemo({ Key key }) : super(key: key);

  @override
  _AnimationDemoState createState() => _AnimationDemoState();
}

class _AnimationDemoState extends State<AnimationDemo> with TickerProviderStateMixin {
  List<_ArcDemo> _allDemos;

  @override
  void initState() {
    super.initState();
    _allDemos = <_ArcDemo>[
      _ArcDemo('POINT', (_ArcDemo demo) {
        return _PointDemo(
          key: demo.key,
          controller: demo.controller,
        );
      }, this),
      _ArcDemo('RECTANGLE', (_ArcDemo demo) {
        return _RectangleDemo(
          key: demo.key,
          controller: demo.controller,
        );
      }, this),
    ];
  }

  Future<void> _play(_ArcDemo demo) async {
    await demo.controller.forward();
    if (demo.key.currentState != null && demo.key.currentState.mounted)
      demo.controller.reverse();
  }

  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: _allDemos.length,
      child: Scaffold(
        appBar: AppBar(
          title: const Text('Animation'),
          bottom: TabBar(
            tabs: _allDemos.map<Tab>((_ArcDemo demo) => Tab(text: demo.title)).toList(),
          ),
        ),
        floatingActionButton: Builder(
          builder: (BuildContext context) {
            return FloatingActionButton(
              child: const Icon(Icons.refresh),
              onPressed: () {
                _play(_allDemos[DefaultTabController.of(context).index]);
              },
            );
          },
        ),
        body: TabBarView(
          children: _allDemos.map<Widget>((_ArcDemo demo) => demo.builder(demo)).toList(),
        ),
      ),
    );
  }
}

void main() {
  runApp(const MaterialApp(
    home: AnimationDemo(),
  ));
}
