import 'package:diameter/components/repeat_on_hold_button.dart';
import 'package:diameter/utils/utils.dart';
import 'package:flutter/material.dart';

class NumberFormField extends StatefulWidget {
  final TextEditingController controller;
  final double min;
  final double? max;
  final double step;
  final String label;
  final String? suffix;
  final void Function(double?) onChanged;
  final bool readOnly;
  final bool showSteppers;
  final bool autoRoundToMultipleOfStep;
  final String? Function(String?)? validator;

  const NumberFormField({
    Key? key,
    required this.controller,
    required this.label,
    required this.onChanged,
    this.suffix,
    this.min = 0,
    this.max,
    this.step = 1,
    this.readOnly = false,
    this.showSteppers = true,
    this.autoRoundToMultipleOfStep = false,
    this.validator,
  }) : super(key: key);

  @override
  _NumberFormFieldState createState() => _NumberFormFieldState();
}

class _NumberFormFieldState extends State<NumberFormField> {
  int precision = 1;

  @override
  void initState() {
    super.initState();
    precision = Utils.getFractionDigitsLength(widget.step) + 1;
  }

  bool onIncrease() {
    double? currentValue = double.tryParse(widget.controller.text);

    if (currentValue != null &&
        (widget.max == null || currentValue + widget.step <= widget.max!)) {
      widget.onChanged(
          Utils.addDoublesWithPrecision(currentValue, widget.step, precision));
      setState(() {});
      return true;
    }
    return false;
  }

  bool onDecrease() {
    double? currentValue = double.tryParse(widget.controller.text);

    if (currentValue != null && (currentValue - widget.step >= widget.min)) {
      widget.onChanged(
          Utils.addDoublesWithPrecision(currentValue, -widget.step, precision));
      setState(() {});
      return true;
    }
    return false;
  }

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisSize: MainAxisSize.min,
      children: [
        widget.showSteppers
            ? RepeatOnHoldButton(
                onTap: onDecrease,
                child: IconButton(
                  onPressed: double.tryParse(widget.controller.text) != null &&
                          (double.parse(widget.controller.text) - widget.step >=
                              widget.min)
                      ? onDecrease
                      : null,
                  icon: const Icon(Icons.remove),
                ),
              )
            : Container(),
        Expanded(
          child: TextFormField(
            readOnly: widget.readOnly,
            controller: widget.controller,
            decoration: InputDecoration(
              labelText: widget.label,
              suffixText: widget.suffix,
            ),
            keyboardType: TextInputType.numberWithOptions(
                decimal: widget.step > 0 && widget.step < 1,
                signed: widget.min.isNegative),
            onChanged: (input) async {
              await Future.delayed(const Duration(seconds: 1));
              double? value = double.tryParse(input);
              if (widget.autoRoundToMultipleOfStep) {
                value = value != null ? Utils.roundToMultipleOfBase(value, widget.step) : null;
              }
              widget.onChanged(value);
            },
            validator: widget.validator,
          ),
        ),
        widget.showSteppers
            ? RepeatOnHoldButton(
                onTap: onIncrease,
                child: IconButton(
                  onPressed: double.tryParse(widget.controller.text) != null &&
                          (widget.max == null ||
                              double.parse(widget.controller.text) +
                                      widget.step <=
                                  widget.max!)
                      ? onIncrease
                      : null,
                  icon: const Icon(Icons.add),
                ),
              )
            : Container(),
      ],
    );
  }
}
