import 'dart:math' show pi;

import 'package:flutter/widgets.dart';

class FeedbackPen extends StatefulWidget {
  const FeedbackPen({
    Key key,
    @required this.color,
  })  : assert(color != null),
        super(key: key);

  final Color color;

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

class _FeedbackPenState extends State<FeedbackPen>
    with SingleTickerProviderStateMixin {
  AnimationController _animationController;
  Animation<Offset> _slideAnimation;

  Color _currentColor;
  Color _nextColor;

  @override
  void initState() {
    super.initState();
    _currentColor = widget.color;
    _nextColor = widget.color;

    _animationController = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 150),
    )..addStatusListener((status) {
        if (status == AnimationStatus.completed) {
          setState(() {
            _currentColor = _nextColor;
            _animationController.reverse();
          });
        }
      });

    _slideAnimation = Tween<Offset>(
      begin: Offset.zero,
      end: const Offset(0, 1),
    ).animate(CurvedAnimation(
      parent: _animationController,
      curve: Curves.easeOut,
      reverseCurve: Curves.easeIn,
    ));
  }

  @override
  void didUpdateWidget(FeedbackPen oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (oldWidget.color != widget.color) {
      _nextColor = widget.color;
      _animationController.forward();
    }
  }

  @override
  Widget build(BuildContext context) {
    return ClipRect(
      child: SlideTransition(
        position: _slideAnimation,
        child: IntrinsicHeight(
          child: CustomPaint(
            foregroundPainter: _PenNosePainter(_currentColor),
            child: Image.asset(
              'assets/images/pen.png',
              package: 'wiredash',
            ),
          ),
        ),
      ),
    );
  }

  @override
  void dispose() {
    _animationController.dispose();
    super.dispose();
  }
}

class _PenNosePainter extends CustomPainter {
  _PenNosePainter(this._color)
      : assert(_color != null),
        _nosePaint = Paint()
          ..color = _color.withOpacity(0.8)
          ..style = PaintingStyle.fill;

  final Color _color;
  final Paint _nosePaint;

  @override
  void paint(Canvas canvas, Size size) {
    canvas.drawArc(
      Rect.fromCircle(center: Offset(size.width / 2, 20), radius: 6.5),
      pi * 0.1,
      -pi * 1.2,
      false,
      _nosePaint,
    );
  }

  @override
  bool shouldRepaint(_PenNosePainter oldDelegate) =>
      oldDelegate._color != _color;
}
