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

// Flutter code sample for [TextFieldTapRegion].

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('TextFieldTapRegion Example')),
        body: const TextFieldTapRegionExample(),
      ),
    );
  }
}

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

  @override
  State<TextFieldTapRegionExample> createState() => _TextFieldTapRegionExampleState();
}

class _TextFieldTapRegionExampleState extends State<TextFieldTapRegionExample> {
  int value = 0;

  @override
  Widget build(BuildContext context) {
    return ListView(
      children: <Widget>[
        Center(
          child: Padding(
            padding: const EdgeInsets.all(20.0),
            child: SizedBox(
              width: 150,
              height: 80,
              child: IntegerSpinnerField(
                value: value,
                autofocus: true,
                onChanged: (int newValue) {
                  if (value == newValue) {
                    // Avoid unnecessary redraws.
                    return;
                  }
                  setState(() {
                    // Update the value and redraw.
                    value = newValue;
                  });
                },
              ),
            ),
          ),
        ),
      ],
    );
  }
}

/// An integer example of the generic [SpinnerField] that validates input and
/// increments by a delta.
class IntegerSpinnerField extends StatelessWidget {
  const IntegerSpinnerField({
    super.key,
    required this.value,
    this.autofocus = false,
    this.delta = 1,
    this.onChanged,
  });

  final int value;
  final bool autofocus;
  final int delta;
  final ValueChanged<int>? onChanged;

  @override
  Widget build(BuildContext context) {
    return SpinnerField<int>(
      value: value,
      onChanged: onChanged,
      autofocus: autofocus,
      fromString: (String stringValue) => int.tryParse(stringValue) ?? value,
      increment: (int i) => i + delta,
      decrement: (int i) => i - delta,
      // Add a text formatter that only allows integer values and a leading
      // minus sign.
      inputFormatters: <TextInputFormatter>[
        TextInputFormatter.withFunction(
          (TextEditingValue oldValue, TextEditingValue newValue) {
            String newString;
            if (newValue.text.startsWith('-')) {
              newString = '-${newValue.text.replaceAll(RegExp(r'\D'), '')}';
            } else {
              newString = newValue.text.replaceAll(RegExp(r'\D'), '');
            }
            return newValue.copyWith(
              text: newString,
              selection: newValue.selection.copyWith(
                baseOffset: newValue.selection.baseOffset.clamp(0, newString.length),
                extentOffset: newValue.selection.extentOffset.clamp(0, newString.length),
              ),
            );
          },
        )
      ],
    );
  }
}

/// A generic "spinner" field example which adds extra buttons next to a
/// [TextField] to increment and decrement the value.
///
/// This widget uses [TextFieldTapRegion] to indicate that tapping on the
/// spinner buttons should not cause the text field to lose focus.
class SpinnerField<T> extends StatefulWidget {
  SpinnerField({
    super.key,
    required this.value,
    required this.fromString,
    this.autofocus = false,
    String Function(T value)? asString,
    this.increment,
    this.decrement,
    this.onChanged,
    this.inputFormatters = const <TextInputFormatter>[],
  }) : asString = asString ?? ((T value) => value.toString());

  final T value;
  final T Function(T value)? increment;
  final T Function(T value)? decrement;
  final String Function(T value) asString;
  final T Function(String value) fromString;
  final ValueChanged<T>? onChanged;
  final List<TextInputFormatter> inputFormatters;
  final bool autofocus;

  @override
  State<SpinnerField<T>> createState() => _SpinnerFieldState<T>();
}

class _SpinnerFieldState<T> extends State<SpinnerField<T>> {
  TextEditingController controller = TextEditingController();

  @override
  void initState() {
    super.initState();
    _updateText(widget.asString(widget.value));
  }

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }

  @override
  void didUpdateWidget(covariant SpinnerField<T> oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (oldWidget.asString != widget.asString || oldWidget.value != widget.value) {
      final String newText = widget.asString(widget.value);
      _updateText(newText);
    }
  }

  void _updateText(String text, {bool collapsed = true}) {
    if (text != controller.text) {
      controller.value = TextEditingValue(
        text: text,
        selection: collapsed
            ? TextSelection.collapsed(offset: text.length)
            : TextSelection(baseOffset: 0, extentOffset: text.length),
      );
    }
  }

  void _spin(T Function(T value)? spinFunction) {
    if (spinFunction == null) {
      return;
    }
    final T newValue = spinFunction(widget.value);
    widget.onChanged?.call(newValue);
    _updateText(widget.asString(newValue), collapsed: false);
  }

  void _increment() {
    _spin(widget.increment);
  }

  void _decrement() {
    _spin(widget.decrement);
  }

  @override
  Widget build(BuildContext context) {
    return CallbackShortcuts(
      bindings: <ShortcutActivator, VoidCallback>{
        const SingleActivator(LogicalKeyboardKey.arrowUp): _increment,
        const SingleActivator(LogicalKeyboardKey.arrowDown): _decrement,
      },
      child: Row(
        children: <Widget>[
          Expanded(
            child: TextField(
              autofocus: widget.autofocus,
              inputFormatters: widget.inputFormatters,
              decoration: const InputDecoration(
                border: OutlineInputBorder(),
              ),
              onChanged: (String value) => widget.onChanged?.call(widget.fromString(value)),
              controller: controller,
              textAlign: TextAlign.center,
            ),
          ),
          const SizedBox(width: 12),
          // Without this TextFieldTapRegion, tapping on the buttons below would
          // increment the value, but it would cause the text field to be
          // unfocused, since tapping outside of a text field should unfocus it
          // on non-mobile platforms.
          TextFieldTapRegion(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Expanded(
                  child: OutlinedButton(
                    onPressed: _increment,
                    child: const Icon(Icons.add),
                  ),
                ),
                Expanded(
                  child: OutlinedButton(
                    onPressed: _decrement,
                    child: const Icon(Icons.remove),
                  ),
                ),
              ],
            ),
          )
        ],
      ),
    );
  }
}
