// Copyright 2015 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/rendering.dart';
import 'package:flutter/widgets.dart';

import 'constants.dart';
import 'debug.dart';
import 'theme.dart';
import 'toggleable.dart';

const double _kDiameter = 16.0;
const double _kOuterRadius = _kDiameter / 2.0;
const double _kInnerRadius = 5.0;

class Radio<T> extends StatelessComponent {
  Radio({
    Key key,
    this.value,
    this.groupValue,
    this.activeColor,
    this.onChanged
  }) : super(key: key);

  final T value;
  final T groupValue;
  final Color activeColor;
  final ValueChanged<T> onChanged;

  bool get _enabled => onChanged != null;

  Color _getInactiveColor(ThemeData themeData) {
    return _enabled ? themeData.unselectedColor : themeData.disabledColor;
  }

  void _handleChanged(bool selected) {
    if (selected)
      onChanged(value);
  }

  Widget build(BuildContext context) {
    assert(debugCheckHasMaterial(context));
    ThemeData themeData = Theme.of(context);
    return new Semantics(
      checked: value == groupValue,
      child: new _RadioRenderObjectWidget(
        selected: value == groupValue,
        activeColor: activeColor ?? themeData.accentColor,
        inactiveColor: _getInactiveColor(themeData),
        onChanged: _enabled ? _handleChanged : null
      )
    );
  }
}

class _RadioRenderObjectWidget extends LeafRenderObjectWidget {
  _RadioRenderObjectWidget({
    Key key,
    this.selected,
    this.activeColor,
    this.inactiveColor,
    this.onChanged
  }) : super(key: key) {
    assert(selected != null);
    assert(activeColor != null);
    assert(inactiveColor != null);
  }

  final bool selected;
  final Color inactiveColor;
  final Color activeColor;
  final ValueChanged<bool> onChanged;

  _RenderRadio createRenderObject() => new _RenderRadio(
    value: selected,
    activeColor: activeColor,
    inactiveColor: inactiveColor,
    onChanged: onChanged
  );

  void updateRenderObject(_RenderRadio renderObject, _RadioRenderObjectWidget oldWidget) {
    renderObject.value = selected;
    renderObject.activeColor = activeColor;
    renderObject.inactiveColor = inactiveColor;
    renderObject.onChanged = onChanged;
  }
}

class _RenderRadio extends RenderToggleable {
  _RenderRadio({
    bool value,
    Color activeColor,
    Color inactiveColor,
    ValueChanged<bool> onChanged
  }): super(
    value: value,
    activeColor: activeColor,
    inactiveColor: inactiveColor,
    onChanged: onChanged,
    size: const Size(2 * kRadialReactionRadius, 2 * kRadialReactionRadius)
  );

  bool get isInteractive => super.isInteractive && !value;

  void paint(PaintingContext context, Offset offset) {
    final Canvas canvas = context.canvas;

    paintRadialReaction(canvas, offset + const Offset(kRadialReactionRadius, kRadialReactionRadius));

    Point center = (offset & size).center;
    Color radioColor = onChanged != null ? activeColor : inactiveColor;

    // Outer circle
    Paint paint = new Paint()
      ..color = Color.lerp(inactiveColor, radioColor, position.value)
      ..style = PaintingStyle.stroke
      ..strokeWidth = 2.0;
    canvas.drawCircle(center, _kOuterRadius, paint);

    // Inner circle
    if (!position.isDismissed) {
      paint.style = PaintingStyle.fill;
      canvas.drawCircle(center, _kInnerRadius * position.value, paint);
    }
  }
}
