// Copyright 2014 The Flutter 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/foundation.dart';
import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

enum LerpTarget {
  circle,
  roundedRect,
  rect,
  stadium,
  polygon,
  star,
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  static final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
  final OptionModel _model = OptionModel();
  final TextEditingController textController = TextEditingController();

  @override
  void initState() {
    super.initState();
    _model.addListener(_modelChanged);
  }

  @override
  void dispose() {
    super.dispose();
    _model.removeListener(_modelChanged);
  }

  void _modelChanged() {
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        key: scaffoldKey,
        appBar: AppBar(
          title: const Text('Star Border'),
          backgroundColor: const Color(0xff323232),
        ),
        body: Column(
          children: <Widget>[
            Container(color: Colors.grey.shade200, child: Options(_model)),
            Expanded(
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: <Widget>[
                  Container(
                    key: UniqueKey(),
                    alignment: Alignment.center,
                    width: 300,
                    height: 200,
                    decoration: ShapeDecoration(
                      color: Colors.blue.shade100,
                      shape: lerpBorder(
                        StarBorder.polygon(
                          side: const BorderSide(strokeAlign: StrokeAlign.center, width: 2),
                          sides: _model.points,
                          pointRounding: _model.pointRounding,
                          rotation: _model.rotation,
                          squash: _model.squash,
                        ),
                        _model._lerpTarget,
                        _model._lerpAmount,
                        to: _model.lerpTo,
                      )!,
                    ),
                    child: const Text('Polygon'),
                  ),
                  Container(
                    key: UniqueKey(),
                    alignment: Alignment.center,
                    width: 300,
                    height: 200,
                    decoration: ShapeDecoration(
                      color: Colors.blue.shade100,
                      shape: lerpBorder(
                        StarBorder(
                          side: const BorderSide(strokeAlign: StrokeAlign.center, width: 2),
                          points: _model.points,
                          innerRadiusRatio: _model.innerRadiusRatio,
                          pointRounding: _model.pointRounding,
                          valleyRounding: _model.valleyRounding,
                          rotation: _model.rotation,
                          squash: _model.squash,
                        ),
                        _model._lerpTarget,
                        _model._lerpAmount,
                        to: _model.lerpTo,
                      )!,
                    ),
                    child: const Text('Star'),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class OptionModel extends ChangeNotifier {
  double get pointRounding => _pointRounding;
  double _pointRounding = 0.0;
  set pointRounding(double value) {
    if (value != _pointRounding) {
      _pointRounding = value;
      if (_valleyRounding + _pointRounding > 1) {
        _valleyRounding = 1.0 - _pointRounding;
      }
      notifyListeners();
    }
  }

  double get valleyRounding => _valleyRounding;
  double _valleyRounding = 0.0;
  set valleyRounding(double value) {
    if (value != _valleyRounding) {
      _valleyRounding = value;
      if (_valleyRounding + _pointRounding > 1) {
        _pointRounding = 1.0 - _valleyRounding;
      }
      notifyListeners();
    }
  }

  double get squash => _squash;
  double _squash = 0.0;
  set squash(double value) {
    if (value != _squash) {
      _squash = value;
      notifyListeners();
    }
  }

  double get rotation => _rotation;
  double _rotation = 0.0;
  set rotation(double value) {
    if (value != _rotation) {
      _rotation = value;
      notifyListeners();
    }
  }

  double get innerRadiusRatio => _innerRadiusRatio;
  double _innerRadiusRatio = 0.4;
  set innerRadiusRatio(double value) {
    if (value != _innerRadiusRatio) {
      _innerRadiusRatio = clampDouble(value, 0.0001, double.infinity);
      notifyListeners();
    }
  }

  double get points => _points;
  double _points = 5;
  set points(double value) {
    if (value != _points) {
      _points = value;
      notifyListeners();
    }
  }

  double get lerpAmount => _lerpAmount;
  double _lerpAmount = 0.0;
  set lerpAmount(double value) {
    if (value != _lerpAmount) {
      _lerpAmount = value;
      notifyListeners();
    }
  }

  bool get lerpTo => _lerpTo;
  bool _lerpTo = true;
  set lerpTo(bool value) {
    if (_lerpTo != value) {
      _lerpTo = value;
      notifyListeners();
    }
  }

  LerpTarget get lerpTarget => _lerpTarget;
  LerpTarget _lerpTarget = LerpTarget.circle;
  set lerpTarget(LerpTarget value) {
    if (value != _lerpTarget) {
      _lerpTarget = value;
      notifyListeners();
    }
  }

  void reset() {
    final OptionModel defaultModel = OptionModel();
    _pointRounding = defaultModel.pointRounding;
    _valleyRounding = defaultModel.valleyRounding;
    _rotation = defaultModel.rotation;
    _squash = defaultModel.squash;
    _lerpAmount = defaultModel.lerpAmount;
    _lerpTo = defaultModel.lerpTo;
    _lerpTarget = defaultModel.lerpTarget;
    _innerRadiusRatio = defaultModel._innerRadiusRatio;
    _points = defaultModel.points;
    notifyListeners();
  }
}

class LabeledCheckbox extends StatelessWidget {
  const LabeledCheckbox({super.key, required this.label, this.onChanged, this.value});

  final String label;
  final ValueChanged<bool?>? onChanged;
  final bool? value;

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisSize: MainAxisSize.min,
      children: <Widget>[
        Checkbox(
          onChanged: onChanged,
          value: value,
        ),
        Text(label),
      ],
    );
  }
}

class Options extends StatefulWidget {
  const Options(this.model, {super.key});

  final OptionModel model;

  @override
  State<Options> createState() => _OptionsState();
}

class _OptionsState extends State<Options> {
  @override
  void initState() {
    super.initState();
    widget.model.addListener(_modelChanged);
  }

  @override
  void didUpdateWidget(Options oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (widget.model != oldWidget.model) {
      oldWidget.model.removeListener(_modelChanged);
      widget.model.addListener(_modelChanged);
    }
  }

  @override
  void dispose() {
    super.dispose();
    widget.model.removeListener(_modelChanged);
  }

  void _modelChanged() {
    setState(() {});
  }

  double sliderValue = 0.0;

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.fromLTRB(5.0, 0.0, 5.0, 10.0),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          Row(
            children: <Widget>[
              Expanded(
                child: ControlSlider(
                  label: 'Point Rounding',
                  value: widget.model.pointRounding,
                  onChanged: (double value) {
                    widget.model.pointRounding = value;
                  },
                ),
              ),
              Expanded(
                child: ControlSlider(
                  label: 'Valley Rounding',
                  value: widget.model.valleyRounding,
                  onChanged: (double value) {
                    widget.model.valleyRounding = value;
                  },
                ),
              ),
            ],
          ),
          Row(
            children: <Widget>[
              Expanded(
                child: ControlSlider(
                  label: 'Squash',
                  value: widget.model.squash,
                  onChanged: (double value) {
                    widget.model.squash = value;
                  },
                ),
              ),
              Expanded(
                child: ControlSlider(
                  label: 'Rotation',
                  value: widget.model.rotation,
                  max: 360,
                  onChanged: (double value) {
                    widget.model.rotation = value;
                  },
                ),
              ),
            ],
          ),
          Row(
            children: <Widget>[
              Expanded(
                child: Row(
                  children: <Widget>[
                    Expanded(
                      child: ControlSlider(
                        label: 'Points',
                        value: widget.model.points,
                        min: 2,
                        max: 20,
                        onChanged: (double value) {
                          widget.model.points = value;
                        },
                      ),
                    ),
                    OutlinedButton(
                        child: const Text('Nearest'),
                        onPressed: () {
                          widget.model.points = widget.model.points.roundToDouble();
                        }),
                  ],
                ),
              ),
              Expanded(
                child: ControlSlider(
                  label: 'Inner Radius',
                  value: widget.model.innerRadiusRatio,
                  onChanged: (double value) {
                    widget.model.innerRadiusRatio = value;
                  },
                ),
              ),
            ],
          ),
          Row(
            children: <Widget>[
              Expanded(
                flex: 2,
                child: Padding(
                  padding: const EdgeInsetsDirectional.only(end: 8.0),
                  child: ControlSlider(
                    label: 'Lerp',
                    value: widget.model.lerpAmount,
                    onChanged: (double value) {
                      widget.model.lerpAmount = value;
                    },
                  ),
                ),
              ),
              Padding(
                padding: const EdgeInsetsDirectional.only(start: 8.0, end: 20.0),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: <Widget>[
                    Row(children: <Widget>[
                      Radio<bool>(
                          value: true,
                          groupValue: widget.model.lerpTo,
                          onChanged: (bool? value) {
                            widget.model.lerpTo = value!;
                          }),
                      const Text('To'),
                    ]),
                    Row(children: <Widget>[
                      Radio<bool>(
                          value: false,
                          groupValue: widget.model.lerpTo,
                          onChanged: (bool? value) {
                            widget.model.lerpTo = value!;
                          }),
                      const Text('From'),
                    ])
                  ],
                ),
              ),
              Expanded(
                child: Row(
                  children: <Widget>[
                    Expanded(
                      child: DropdownButton<LerpTarget>(
                        items: LerpTarget.values.map<DropdownMenuItem<LerpTarget>>((LerpTarget target) {
                          return DropdownMenuItem<LerpTarget>(value: target, child: Text(target.name));
                        }).toList(),
                        value: widget.model.lerpTarget,
                        onChanged: (LerpTarget? value) {
                          if (value == null) {
                            return;
                          }
                          widget.model.lerpTarget = value;
                        },
                      ),
                    ),
                  ],
                ),
              ),
            ],
          ),
          ElevatedButton(
            onPressed: () {
              widget.model.reset();
              sliderValue = 0.0;
            },
            child: const Text('Reset'),
          ),
        ],
      ),
    );
  }
}

class ControlSlider extends StatelessWidget {
  const ControlSlider({
    super.key,
    required this.label,
    required this.value,
    required this.onChanged,
    this.min = 0.0,
    this.max = 1.0,
  });

  final String label;
  final double value;
  final void Function(double value) onChanged;
  final double min;
  final double max;

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(4.0),
      child: Row(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          Text(label),
          Expanded(
            child: Slider(
              label: value.toStringAsFixed(1),
              onChanged: onChanged,
              min: min,
              max: max,
              value: value,
            ),
          ),
          Text(
            value.toStringAsFixed(3),
          ),
        ],
      ),
    );
  }
}

const Color lerpToColor = Colors.red;
const BorderSide lerpToBorder = BorderSide(width: 5, color: lerpToColor);

ShapeBorder? lerpBorder(StarBorder border, LerpTarget target, double t, {bool to = true}) {
  switch (target) {
    case LerpTarget.circle:
      if (to) {
        return border.lerpTo(const CircleBorder(side: lerpToBorder, eccentricity: 0.5), t);
      } else {
        return border.lerpFrom(const CircleBorder(side: lerpToBorder, eccentricity: 0.5), t);
      }
    case LerpTarget.roundedRect:
      if (to) {
        return border.lerpTo(
          const RoundedRectangleBorder(
            side: lerpToBorder,
            borderRadius: BorderRadius.all(
              Radius.circular(10),
            ),
          ),
          t,
        );
      } else {
        return border.lerpFrom(
          const RoundedRectangleBorder(
            side: lerpToBorder,
            borderRadius: BorderRadius.all(
              Radius.circular(10),
            ),
          ),
          t,
        );
      }
    case LerpTarget.rect:
      if (to) {
        return border.lerpTo(const RoundedRectangleBorder(side: lerpToBorder), t);
      } else {
        return border.lerpFrom(const RoundedRectangleBorder(side: lerpToBorder), t);
      }
    case LerpTarget.stadium:
      if (to) {
        return border.lerpTo(const StadiumBorder(side: lerpToBorder), t);
      } else {
        return border.lerpFrom(const StadiumBorder(side: lerpToBorder), t);
      }
    case LerpTarget.polygon:
      if (to) {
        return border.lerpTo(const StarBorder.polygon(side: lerpToBorder, sides: 4), t);
      } else {
        return border.lerpFrom(const StarBorder.polygon(side: lerpToBorder, sides: 4), t);
      }
    case LerpTarget.star:
      if (to) {
        return border.lerpTo(const StarBorder(side: lerpToBorder, innerRadiusRatio: .5), t);
      } else {
        return border.lerpFrom(const StarBorder(side: lerpToBorder, innerRadiusRatio: .5), t);
      }
  }
}
