// Copyright 2020 The Fuchsia 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 'dart:math';

import 'package:flutter/material.dart';

const backgroundColor = Color(0xFFEBD4B3);
const hourHandColor = Color(0xFFFD4763);
const minuteHandColor = Color(0x7FFF7284);
const secondHandColor = Colors.white;
const shadowColor = Color(0x0D000000);
const radius = 0.4;
const thickness = radius / 20.0;
const offset = radius / 5.0;
const elevation = 0.01;

void main() => runApp(ClockFace());

class ClockFace extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return ClockFaceState();
  }
}

class ClockFaceState extends State<ClockFace> {
  DateTime _now;
  Timer _timer;

  @override
  void initState() {
    super.initState();
    _now = DateTime.now().toUtc();
    _timer = Timer.periodic(const Duration(milliseconds: 16), _setNow);
  }

  void _setNow(Timer _timer) {
    setState(() {
      _now = DateTime.now().toUtc();
    });
  }

  @override
  void dispose() {
    _timer.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return CustomPaint(
      painter: ClockPainter(_now),
      child: Container(),
    );
  }
}

class Hand {
  RRect _hand;
  RRect _shadow;
  final Color _color;
  final Point _pos;
  final double _angle;

  Hand(this._pos, double thickness, double length, double offset, this._color,
      double shadowOffset, this._angle) {
    _hand = RRect.fromRectAndRadius(
        Rect.fromLTWH(_pos.x - (thickness / 2.0 + offset),
            _pos.y - thickness / 2.0, length, thickness),
        Radius.circular(thickness / 2.0));
    _shadow = RRect.fromRectAndRadius(
        _hand.outerRect.translate(shadowOffset, shadowOffset * 2.0),
        _hand.tlRadius);
  }

  void paintHand(Canvas canvas) {
    canvas
      ..save()
      ..translate(_pos.x, _pos.y)
      ..rotate(_angle)
      ..translate(-_pos.x, -_pos.y)
      ..drawRRect(_hand, Paint()..color = _color)
      ..restore();
  }

  Path shadowPath() {
    var path = Path()..addRRect(_shadow);

    var matrix = Matrix4.identity()
      ..translate(_pos.x, _pos.y)
      ..rotateZ(_angle)
      ..translate(-_pos.x, -_pos.y);

    return path.transform(matrix.storage);
  }
}

class ClockPainter extends CustomPainter {
  final DateTime _now;

  ClockPainter(this._now);

  double ratioToAngle(double ratio, double total) {
    const rewind = -0.25; // account for 3 to 12 o'clock rewinding
    return ((rewind + ratio / total) % 1.0) * 2.0 * pi;
  }

  @override
  void paint(Canvas canvas, Size size) {
    var background = Offset.zero & size;
    canvas.drawRect(background, Paint()..color = backgroundColor);

    var scale = min(size.width, size.height);
    var center = Point(size.width / 2.0, size.height / 2.0);
    var second =
        (_now.second + 1).toDouble() + _now.millisecond.toDouble() / 1e+3;
    var minute = (_now.minute + 1).toDouble() + second / 60.0;
    var hour = (_now.hour % 12 + 1).toDouble() + minute / 60.0;

    var hourAngle = ratioToAngle(hour, 12.0);
    var minuteAngle = ratioToAngle(minute, 60.0);
    var secondAngle = ratioToAngle(second, 60.0);

    var secondHand = Hand(
        center,
        scale * thickness / 2.0,
        scale * (radius + offset),
        scale * offset,
        secondHandColor,
        scale * elevation,
        secondAngle);
    var minuteHand = Hand(center, scale * thickness, scale * radius, 0.0,
        minuteHandColor, scale * elevation, minuteAngle);
    var hourHand = Hand(center, scale * thickness * 2.0, scale * radius,
        scale * offset, hourHandColor, scale * elevation, hourAngle);

    var shadowHourSecond = Path.combine(
        PathOperation.union, hourHand.shadowPath(), secondHand.shadowPath());
    var shadowAll = Path.combine(
        PathOperation.union, shadowHourSecond, minuteHand.shadowPath());

    canvas
      ..drawPath(shadowHourSecond, Paint()..color = shadowColor)
      ..drawPath(shadowAll, Paint()..color = shadowColor);

    secondHand.paintHand(canvas);
    minuteHand.paintHand(canvas);
    hourHand.paintHand(canvas);
  }

  @override
  bool shouldRepaint(ClockPainter oldDelegate) => true;
}
