// 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:wyatt_crud_bloc/src/features/crud/cubit/crud_cubit.dart';

class CrudBuilder<I, L, S, E> extends StatelessWidget {
  /// `<I, L, S, E>`
  ///
  /// - I: the Initial State
  /// - L: the Loading State
  /// - S: the Success State
  /// - E: the Error State
  const CrudBuilder({
    required this.state,
    required this.builder,
    required this.initialBuilder,
    required this.loadingBuilder,
    required this.errorBuilder,
    this.unknownBuilder,
    super.key,
  });

  /// `<CrudInitial, CrudLoading, S extends CrudSuccess, CrudError>`
  ///
  /// - S: the Success State
  ///
  /// For CrudStates only.
  static CrudBuilder<CrudInitial, CrudLoading, CrudSuccess, CrudError>
      typed<S extends CrudSuccess>({
    required CrudState state,
    required Widget Function(BuildContext, S) builder,
    required Widget Function(BuildContext, CrudInitial) initialBuilder,
    required Widget Function(BuildContext, CrudLoading) loadingBuilder,
    required Widget Function(BuildContext, CrudError) errorBuilder,
    Widget Function(BuildContext, Object)? unknownBuilder,
  }) =>
          CrudBuilder<CrudInitial, CrudLoading, S, CrudError>(
            state: state,
            builder: builder,
            initialBuilder: initialBuilder,
            loadingBuilder: loadingBuilder,
            errorBuilder: errorBuilder,
            unknownBuilder: unknownBuilder,
          );

  final Object state;
  final Widget Function(BuildContext context, S state) builder;
  final Widget Function(BuildContext context, I state) initialBuilder;
  final Widget Function(BuildContext context, L state) loadingBuilder;
  final Widget Function(BuildContext context, E state) errorBuilder;
  final Widget Function(BuildContext context, Object state)? unknownBuilder;

  @override
  Widget build(BuildContext context) => Builder(
        builder: (context) {
          if (state is S) {
            return builder(context, state as S);
          } else if (state is E) {
            return errorBuilder(context, state as E);
          } else if (state is L) {
            return loadingBuilder(context, state as L);
          } else if (state is I) {
            return initialBuilder(context, state as I);
          } else {
            return unknownBuilder?.call(context, state) ??
                Center(
                  child: Text(
                    'Unknown state: $state',
                  ),
                );
          }
        },
      );
}
