import 'package:flutter/widgets.dart';

class _Scope extends InheritedWidget {
  _Scope({
    Key? key,
    this.formState,
    this.generation,
    required this.child,
  }) : super(key: key, child: child);

  final Widget child;
  final int? generation;
  final WFormState? formState;

  ///通过验证[generation]的变化进行刷新
  @override
  bool updateShouldNotify(_Scope oldWidget) =>
      generation != oldWidget.generation;
}

///基于[Form]进行改造，实现双向绑定
///
///[WFormState.values]可获取到表单全部数据
///
///[WFormState.setValue]设置一个对应[field]的值
///
///[WFormState.mergeValues]合并[values]
class WForm extends StatefulWidget {
  WForm({
    Key? key,
    this.child,
    this.autovalidateMode = AutovalidateMode.disabled,
    this.autoLostFocus = true,
    this.onWillPop,
    this.onChanged,
    this.initialValues,
  }) : super(key: key);

  static WFormState? of(BuildContext context) {
    final _Scope? scope = context.dependOnInheritedWidgetOfExactType<_Scope>();
    return scope?.formState;
  }

  ///失去焦点
  static void lostFocus(BuildContext context) =>
      FocusScope.of(context).requestFocus(
        FocusNode(),
      );

  final AutovalidateMode autovalidateMode;

  ///自动失去焦点
  final bool autoLostFocus;

  final WillPopCallback? onWillPop;

  final VoidCallback? onChanged;

  final Widget? child;

  final Map<String, dynamic>? initialValues;
  @override
  WFormState createState() => WFormState();
}

class WFormState extends State<WForm> {
  final _formKey = GlobalKey<FormState>();
  int _generation = 0;

  Map<String, dynamic>? _values;
  Map<String, dynamic>? _initialValues;

  @override
  void initState() {
    ///深拷贝
    _values = Map.from(widget.initialValues ?? {});

    ///深拷贝
    _initialValues = Map.from(widget.initialValues ?? {});
    super.initState();
  }

  void _initValue(String field, value) {
    _values![field] = value;
  }

  @override
  Widget build(BuildContext context) {
    Widget? current = widget.child;
    if (widget.autoLostFocus) {
      current = GestureDetector(
        behavior: HitTestBehavior.translucent,
        onTap: () => FocusScope.of(context).requestFocus(FocusNode()),
        child: current,
      );
    }
    current = Form(
      key: _formKey,
      child: current!,
      autovalidateMode: widget.autovalidateMode,
      onWillPop: widget.onWillPop,
      onChanged: widget.onChanged,
    );

    current = _Scope(
      formState: this,
      generation: _generation,
      child: current,
    );
    return current;
  }

  Map<String, dynamic>? get values => _values;
  Map<String, dynamic> get initialValues => _initialValues ?? {};

  ///保存，同[FormState.save]
  void save() => _formKey.currentState?.save();

  ///初始化，同[FormState.reset]
  void reset() {
    _formKey.currentState?.reset();
    _generation++;
  }

  ///验证表单，同[FormState.validate]
  void validate() => _formKey.currentState?.validate();

  ///[WFormState.setValue]设置一个对应[field]的值
  void setValue(String field, value) {
    if (_values![field] != value) {
      _values![field] = value;
      _generation++;

      setState(() {});
    }
  }

  ///[WFormState.mergeValues]合并[values]
  void mergeValues(Map<String, dynamic> values) {
    final newValues = _values!..addAll(values);
    if (newValues != _values) {
      _values = newValues;
      _generation++;
      setState(() {});
    }
  }
}

typedef WFormFieldBuilder<T> = Widget Function(WFormFieldState<T> fieldState);

///表单项构造
///
/// 与[FormField] 类似

class WFormField<T> extends FormField<T> {
  WFormField({
    Key? key,
    required this.field,
    required WFormFieldBuilder<T> builder,
    FormFieldSetter<T>? onSaved,
    FormFieldValidator<T>? validator,
    AutovalidateMode? autovalidateMode = AutovalidateMode.disabled,
    bool enabled = true,
  })  : assert(field.isNotEmpty, 'field不能为空'),
        super(
          key: key,
          onSaved: onSaved,
          validator: validator,
          autovalidateMode: autovalidateMode,
          enabled: enabled,
          builder: (fieldState) =>
              builder((fieldState as WFormFieldState) as WFormFieldState<T>),
        );
  final String field;
  @override
  WFormFieldState<T> createState() => WFormFieldState<T>();
}

class WFormFieldState<T> extends FormFieldState<T> {
  @override
  WFormField<T> get widget => super.widget as WFormField<T>;

  @override
  T? get value => WForm.of(context)?.values![widget.field];

  T? get initialValue => WForm.of(context)?.initialValues[widget.field];

  String? _errorText;

  String? get errorText => _errorText;

  bool get hasError => _errorText != null;

  @override
  void setValue(T? value, {rebuild = false}) {
    if (widget.field != '') {
      if (rebuild == true) {
        WForm.of(context)!.setValue(widget.field, value);
      } else {
        WForm.of(context)!._initValue(widget.field, value);
      }
    }
    super.setValue(value);
  }

  @override
  void didChange(T? value) {
    setValue(value);
    super.didChange(value);
  }

  @override
  bool validate() {
    if (widget.validator != null) _errorText = widget.validator!(value);
    return hasError;
  }

  @override
  void reset() {
    setValue(initialValue);
    super.reset();
  }
}
