// 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/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:wyatt_bloc_helper/src/bloc_base/bloc_base_consumer_screen.dart';
import 'package:wyatt_bloc_helper/src/utils/smart_provider.dart';

/// {@template bloc_base_screen}
/// Provide AND access to a [Bloc] or [Cubit].
///
/// This extends [BlocBaseConsumerScreen] with the methods
// ignore: comment_references
/// of [BlocBaseProviderScreen].
/// {@endtemplate}
abstract class BlocBaseScreen<Bloc extends BlocBase<State>,
    State extends Object> extends BlocBaseConsumerScreen<Bloc, State> {
  /// {@macro bloc_base_screen}
  const BlocBaseScreen({
    super.key,
    this.lazy = true,
    this.smart = true,
  });

  /// Whether the [Bloc] or [Cubit] should be created lazily.
  /// Defaults to `true` which means the [Bloc] is created only when
  /// accessed the first time, not when provided.
  final bool lazy;

  /// Whether this uses [SmartProvider].
  /// Defaults to `true`. But if you want to provide new Bloc of a same type,
  /// in a sub-tree you may have to disable this.
  final bool smart;

  /// Creates the [Cubit] or [Bloc] to be used.
  Bloc create(BuildContext context);

  /// Initialize the [Bloc] or [Cubit].
  ///
  /// This function is useful when using with [SmartProvider], because
  /// if you want to pass an initial event to your bloc you can pass it in
  /// `create` function but if you re-use the bloc below in the tree this event
  /// will never be re-pass.
  Bloc init(BuildContext context, Bloc bloc) => bloc;

  @override
  Widget build(BuildContext context) => SmartProvider.bloc<Bloc, State>(
        context,
        lazy: lazy,
        enable: smart,
        create: (_) => create(context),
        init: (_, bloc) => init(context, bloc),
        child: super.build(context),
      );
}
