// 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: BorderSide.strokeAlignCenter, 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: BorderSide.strokeAlignCenter, 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);
      }
  }
}
