// 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.

/// An example showing usage of [StarBorder].

import 'package:flutter/material.dart';

const int _kParameterPrecision = 2;

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('StarBorder Example'),
          backgroundColor: const Color(0xff323232),
        ),
        body: const StarBorderExample(),
      ),
    );
  }
}

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

  @override
  State<StarBorderExample> createState() => _StarBorderExampleState();
}

class _StarBorderExampleState extends State<StarBorderExample> {
  final OptionModel _model = OptionModel();
  final TextEditingController _textController = TextEditingController();

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

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

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

  @override
  Widget build(BuildContext context) {
    return DefaultTextStyle(
      style: const TextStyle(
        color: Colors.black,
        fontSize: 14.0,
        fontFamily: 'Roboto',
        fontStyle: FontStyle.normal,
      ),
      child: ListView(
        children: <Widget>[
          Container(
            color: Colors.grey.shade200,
            child: Options(_model),
          ),
          Padding(
            padding: const EdgeInsets.all(18.0),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: <Widget>[
                Expanded(
                  child: ExampleBorder(
                    border: StarBorder(
                      side: const BorderSide(),
                      points: _model.points,
                      innerRadiusRatio: _model.innerRadiusRatio,
                      pointRounding: _model.pointRounding,
                      valleyRounding: _model.valleyRounding,
                      rotation: _model.rotation,
                      squash: _model.squash,
                    ),
                    title: 'Star',
                  ),
                ),
                Expanded(
                  child: ExampleBorder(
                    border: StarBorder.polygon(
                      side: const BorderSide(),
                      sides: _model.points,
                      pointRounding: _model.pointRounding,
                      rotation: _model.rotation,
                      squash: _model.squash,
                    ),
                    title: 'Polygon',
                  ),
                ),
              ],
            ),
          ),
          Row(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              Expanded(
                child: Container(
                  color: Colors.black12,
                  margin: const EdgeInsets.all(16.0),
                  padding: const EdgeInsets.all(16.0),
                  child: SelectableText(_model.starCode),
                ),
              ),
              Expanded(
                child: Container(
                  color: Colors.black12,
                  margin: const EdgeInsets.all(16.0),
                  padding: const EdgeInsets.all(16.0),
                  child: SelectableText(_model.polygonCode),
                ),
              ),
            ],
          ),
        ],
      ),
    );
  }
}

class ExampleBorder extends StatelessWidget {
  const ExampleBorder({
    super.key,
    required this.border,
    required this.title,
  });

  final StarBorder border;
  final String title;

  @override
  Widget build(BuildContext context) {
    return Container(
      alignment: Alignment.center,
      padding: const EdgeInsets.all(20),
      width: 150,
      height: 100,
      decoration: ShapeDecoration(
        color: Colors.blue.shade100,
        shape: border,
      ),
      child: Text(title),
    );
  }
}

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

  @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: 3,
                        max: 20,
                        precision: 1,
                        onChanged: (double value) {
                          widget.model.points = value;
                        },
                      ),
                    ),
                    Tooltip(
                      message: 'Round the number of points to the nearest integer.',
                      child: Padding(
                        padding: const EdgeInsets.all(8.0),
                        child: 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;
                  },
                ),
              ),
            ],
          ),
          ElevatedButton(
            onPressed: () {
              widget.model.reset();
            },
            child: const Text('Reset'),
          ),
        ],
      ),
    );
  }
}

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 = value.clamp(0.0001, double.infinity);
      notifyListeners();
    }
  }

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

  String get starCode {
    return 'Container(\n'
        '  decoration: ShapeDecoration(\n'
        '    shape: StarBorder(\n'
        '      points: ${points.toStringAsFixed(_kParameterPrecision)},\n'
        '      rotation: ${rotation.toStringAsFixed(_kParameterPrecision)},\n'
        '      innerRadiusRatio: ${innerRadiusRatio.toStringAsFixed(_kParameterPrecision)},\n'
        '      pointRounding: ${pointRounding.toStringAsFixed(_kParameterPrecision)},\n'
        '      valleyRounding: ${valleyRounding.toStringAsFixed(_kParameterPrecision)},\n'
        '      squash: ${squash.toStringAsFixed(_kParameterPrecision)},\n'
        '    ),\n'
        '  ),\n'
        ');';
  }

  String get polygonCode {
    return 'Container(\n'
        '  decoration: ShapeDecoration(\n'
        '    shape: StarBorder.polygon(\n'
        '      sides: ${points.toStringAsFixed(_kParameterPrecision)},\n'
        '      rotation: ${rotation.toStringAsFixed(_kParameterPrecision)},\n'
        '      cornerRounding: ${pointRounding.toStringAsFixed(_kParameterPrecision)},\n'
        '      squash: ${squash.toStringAsFixed(_kParameterPrecision)},\n'
        '    ),\n'
        '  ),\n'
        ');';
  }

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

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,
    this.precision = _kParameterPrecision,
  });

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

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