// Copyright (C) 2022 WYATT GROUP
// Please see the AUTHORS file for details.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:form_bloc_example/app/app.dart';
import 'package:form_bloc_example/app/metadata.dart';
import 'package:form_bloc_example/constants.dart';
import 'package:form_bloc_example/simple_custom_form_cubit/simple_custom_form_cubit.dart';
import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';

Color computeColor(Metadata? meta) {
  switch (meta?.category) {
    case Category.perso:
      return Colors.blue;
    case Category.business:
      return Colors.red;
    case null:
      return Colors.green;
  }
}

class _NameInput extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return InputBuilderTextController<SimpleCustomFormCubit, String?, Metadata>(
      field: formFieldName,
      builder:
          (context, cubit, state, field, input, controller, metadata) {
        final meta = state.form.metadataOf<Metadata>(field).extra;
        final color = computeColor(meta);
        return Row(
          children: [
            Container(
              height: 8,
              width: 8,
              decoration: BoxDecoration(
                color: color,
                borderRadius: BorderRadius.circular(8),
              ),
            ),
            const SizedBox(
              width: 20,
            ),
            SizedBox(
              width: MediaQuery.of(context).size.width - 45,
              child: TextField(
                controller: controller,
                onChanged: (value) =>
                    cubit.dataChanged(field, Name.dirty(value)),
                keyboardType: TextInputType.name,
                decoration: InputDecoration(
                  labelText: 'name',
                  helperText: '',
                  errorText: input.validator.invalid ? 'invalid name' : null,
                ),
              ),
            )
          ],
        );
      },
    );
  }
}

class _PhoneInput extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return InputBuilderMetadata<SimpleCustomFormCubit, Metadata>(
      field: formFieldPhone,
      builder: (context, cubit, state, field, input, metadata) {
        final meta = state.form.metadataOf<Metadata>(field).extra;
        final color = computeColor(meta);
        return Row(
          children: [
            Container(
              height: 8,
              width: 8,
              decoration: BoxDecoration(
                color: color,
                borderRadius: BorderRadius.circular(8),
              ),
            ),
            const SizedBox(
              width: 20,
            ),
            SizedBox(
              width: MediaQuery.of(context).size.width - 45,
              child: TextField(
                onChanged: (value) =>
                    cubit.dataChanged(field, Phone.dirty(value)),
                keyboardType: TextInputType.phone,
                decoration: InputDecoration(
                  labelText: 'phone',
                  helperText: '',
                  errorText: input.validator.invalid ? 'invalid phone' : null,
                ),
              ),
            )
          ],
        );
      },
    );
  }
}

class _EmailInput extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return InputBuilder<SimpleCustomFormCubit>(
      field: formFieldEmail,
      builder: (context, cubit, state, field, input) => TextField(
        onChanged: (value) => cubit.dataChanged(field, Email.dirty(value)),
        keyboardType: TextInputType.emailAddress,
        decoration: InputDecoration(
          labelText: 'email',
          helperText: '',
          errorText: input.validator.invalid ? 'invalid email' : null,
        ),
      ),
    );
  }
}

class _CheckListInput extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return InputBuilder<SimpleCustomFormCubit>(
      field: formFieldList,
      builder: (context, cubit, state, field, inputValid) {
        final input = state.form.validatorOf<ListOption<String>>(field);
        final choices = ['c1', 'c2', 'c3'];

        return Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            ListTile(
              title: const Text('Checkbox1'),
              trailing: Checkbox(
                  value: input.value == choices[0],
                  onChanged: (_) {
                    cubit.dataChanged(
                      field,
                      ListOption.dirty(choices: choices, value: choices[0]),
                    );
                  }),
            ),
            ListTile(
              title: const Text('Checkbox2'),
              trailing: Checkbox(
                  value: input.value == choices[1],
                  onChanged: (_) {
                    cubit.dataChanged(
                      field,
                      ListOption.dirty(choices: choices, value: choices[1]),
                    );
                  }),
            ),
            ListTile(
              title: const Text('Checkbox3 (default)'),
              trailing: Checkbox(
                  value: input.value == choices[2],
                  onChanged: (_) {
                    cubit.dataChanged(
                      field,
                      ListOption.dirty(choices: choices, value: choices[2]),
                    );
                  }),
            ),
          ],
        );
      },
    );
  }
}

class _RadioListInput extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return InputBuilder<SimpleCustomFormCubit>(
      field: formFieldRadio,
      builder: ((context, cubit, state, field, inputValid) {
        final input = state.form.validatorOf<TextString>(field);

        return Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            ListTile(
              title: const Text('Radio1'),
              trailing: Radio<bool>(
                  groupValue: true,
                  value: input.value == 'radio1',
                  onChanged: (_) {
                    cubit.dataChanged(
                      field,
                      const TextString.dirty('radio1'),
                    );
                  }),
            ),
            ListTile(
              title: const Text('Radio2'),
              trailing: Radio<bool>(
                  groupValue: true,
                  value: input.value == 'radio2',
                  onChanged: (_) {
                    cubit.dataChanged(
                      field,
                      const TextString.dirty('radio2'),
                    );
                  }),
            ),
            ListTile(
              title: const Text('Radio3'),
              trailing: Radio<bool>(
                  groupValue: true,
                  value: input.value == 'radio3',
                  onChanged: (_) {
                    cubit.dataChanged(
                      field,
                      const TextString.dirty('radio3'),
                    );
                  }),
            ),
          ],
        );
      }),
    );
  }
}

class _CheckHiddenInput extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ListTile(
      title: const Text('This input is not exported'),
      trailing: InputBuilder<SimpleCustomFormCubit>(
        field: formFieldHidden,
        builder: (context, cubit, state, field, inputValid) {
          return Checkbox(
              value: state.form.validatorOf<Boolean>(field).value,
              onChanged: (v) {
                final value = v!; // state is false, so value can't be null

                cubit.dataChanged(
                  field,
                  Boolean.dirty(value: value),
                );
              });
        },
      ),
    );
  }
}

class _CheckIsProInput extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ListTile(
      title: const Text('Are you a pro?'),
      trailing: InputBuilder<SimpleCustomFormCubit>(
        field: formFieldPro,
        builder: (context, cubit, state, field, inputValid) {
          return Checkbox(
              value: state.form.validatorOf<Boolean>(field).value,
              onChanged: (v) {
                final value = v!; // state is false, so value can't be null

                cubit.dataChanged(
                  field,
                  Boolean.dirty(value: value),
                );

                if (value) {
                  cubit.update(App.getProFormData(),
                      operation: SetOperation.union);
                } else {
                  cubit.update(App.getNormalFormData(),
                      operation: SetOperation.intersection);
                }
              });
        },
      ),
    );
  }
}

class _SignUpButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return SubmitBuilder<SimpleCustomFormCubit>(
        builder: (context, cubit, status) {
      return status.isSubmissionInProgress
          ? const CircularProgressIndicator()
          : ElevatedButton(
              onPressed: status.isValidated ? () => cubit.submit() : null,
              child: const Text('SIGN UP'),
            );
    });
  }
}

class _ResetButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return SubmitBuilder<SimpleCustomFormCubit>(
        builder: (context, cubit, status) {
      return ElevatedButton(
        onPressed: () => cubit.reset(),
        child: const Text('RESET'),
      );
    });
  }
}

class SignUpForm extends StatelessWidget {
  const SignUpForm({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return BlocListener<SimpleCustomFormCubit, FormDataState>(
      listener: (context, state) {
        if (state.status.isSubmissionSuccess) {
          Navigator.of(context).pop(); // Never happens here
        } else if (state.status.isSubmissionFailure) {
          ScaffoldMessenger.of(context)
            ..hideCurrentSnackBar()
            ..showSnackBar(
              SnackBar(content: Text(state.errorMessage ?? 'Sign Up Failure')),
            );
        }
      },
      child: Align(
        alignment: const Alignment(0, -1 / 3),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            _NameInput(),
            const SizedBox(height: 8),
            _EmailInput(),
            const SizedBox(height: 8),
            _CheckListInput(),
            const SizedBox(height: 8),
            _RadioListInput(),
            const SizedBox(height: 8),
            _CheckHiddenInput(),
            const SizedBox(height: 8),
            _CheckIsProInput(),
            const SizedBox(height: 8),
            BlocBuilder<SimpleCustomFormCubit, FormDataState>(
              builder: (context, state) {
                if (state.form.validatorOf<Boolean>(formFieldPro).value ??
                    false) {
                  return Column(children: [
                    _PhoneInput(),
                    const SizedBox(height: 8),
                  ]);
                }
                return const SizedBox.shrink();
              },
            ),
            const SizedBox(height: 8),
            _SignUpButton(),
            const SizedBox(height: 8),
            _ResetButton(),
          ],
        ),
      ),
    );
  }
}
