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

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

void main() {
  runApp(
    const MaterialApp(
      home: Scaffold(
        body: Center(child: SimpleUSPhoneNumberEntry()),
      ),
    ),
  );
}

// This implements a custom phone number input field that handles the
// [DeleteCharacterIntent] intent.
class DigitInput extends StatefulWidget {
  const DigitInput({
    super.key,
    required this.controller,
    required this.focusNode,
    this.maxLength,
    this.textInputAction = TextInputAction.next,
  });

  final int? maxLength;
  final TextEditingController controller;
  final TextInputAction textInputAction;
  final FocusNode focusNode;

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

class DigitInputState extends State<DigitInput> {
  late final Action<DeleteCharacterIntent> _deleteTextAction =
      CallbackAction<DeleteCharacterIntent>(
    onInvoke: (DeleteCharacterIntent intent) {
      // For simplicity we delete everything in the section.
      widget.controller.clear();
      return null;
    },
  );

  @override
  Widget build(BuildContext context) {
    return Actions(
      actions: <Type, Action<Intent>>{
        // Make the default `DeleteCharacterIntent` handler overridable.
        DeleteCharacterIntent: Action<DeleteCharacterIntent>.overridable(
            defaultAction: _deleteTextAction, context: context),
      },
      child: TextField(
        controller: widget.controller,
        textInputAction: TextInputAction.next,
        keyboardType: TextInputType.phone,
        focusNode: widget.focusNode,
        decoration: const InputDecoration(
          border: OutlineInputBorder(),
        ),
        inputFormatters: <TextInputFormatter>[
          FilteringTextInputFormatter.digitsOnly,
          LengthLimitingTextInputFormatter(widget.maxLength),
        ],
      ),
    );
  }
}

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

  @override
  State<SimpleUSPhoneNumberEntry> createState() =>
      _SimpleUSPhoneNumberEntryState();
}

class _DeleteDigit extends Action<DeleteCharacterIntent> {
  _DeleteDigit(this.state);

  final _SimpleUSPhoneNumberEntryState state;
  @override
  void invoke(DeleteCharacterIntent intent) {
    assert(callingAction != null);
    callingAction?.invoke(intent);

    if (state.lineNumberController.text.isEmpty &&
        state.lineNumberFocusNode.hasFocus) {
      state.prefixFocusNode.requestFocus();
    }

    if (state.prefixController.text.isEmpty && state.prefixFocusNode.hasFocus) {
      state.areaCodeFocusNode.requestFocus();
    }
  }

  // This action is only enabled when the `callingAction` exists and is
  // enabled.
  @override
  bool get isActionEnabled => callingAction?.isActionEnabled ?? false;
}

class _SimpleUSPhoneNumberEntryState extends State<SimpleUSPhoneNumberEntry> {
  final FocusNode areaCodeFocusNode = FocusNode();
  final TextEditingController areaCodeController = TextEditingController();
  final FocusNode prefixFocusNode = FocusNode();
  final TextEditingController prefixController = TextEditingController();
  final FocusNode lineNumberFocusNode = FocusNode();
  final TextEditingController lineNumberController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Actions(
      actions: <Type, Action<Intent>>{
        DeleteCharacterIntent: _DeleteDigit(this),
      },
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: <Widget>[
          const Expanded(
            child: Text('(', textAlign: TextAlign.center),
          ),
          Expanded(
            flex: 3,
            child: DigitInput(
              focusNode: areaCodeFocusNode,
              controller: areaCodeController,
              maxLength: 3,
            ),
          ),
          const Expanded(
            child: Text(')', textAlign: TextAlign.center),
          ),
          Expanded(
            flex: 3,
            child: DigitInput(
              focusNode: prefixFocusNode,
              controller: prefixController,
              maxLength: 3,
            ),
          ),
          const Expanded(
            child: Text('-', textAlign: TextAlign.center),
          ),
          Expanded(
            flex: 4,
            child: DigitInput(
              focusNode: lineNumberFocusNode,
              controller: lineNumberController,
              textInputAction: TextInputAction.done,
              maxLength: 4,
            ),
          ),
        ],
      ),
    );
  }
}
