// 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(
                    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(
                    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);
      }
  }
}
