// 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';

/// {@template multi_provider}
/// Merges [MultiRepositoryProvider] and [MultiBlocProvider] widgets into 
/// one widget tree.
///
/// [MultiProvider] improves the readability and eliminates the need
/// to nest multiple providers.
///
/// By using [MultiProvider] we can go from:
/// 
/// ```dart
/// MultiRepositoryProvider(
///   providers: [
///     RepositoryProvider<RepositoryA>(create: (context) => RepositoryA()),
///     RepositoryProvider<RepositoryB>(create: (context) => RepositoryB()),
///     RepositoryProvider<RepositoryC>(create: (context) => RepositoryC()),
///   ],
///   child:
///     MultiBlocProvider(
///       providers: [
///         BlocProvider<BlocA>(
///           create: (BuildContext context) => BlocA(),
///         ),
///         BlocProvider<BlocB>(
///           create: (BuildContext context) => BlocB(),
///         ),
///         BlocProvider<BlocC>(
///           create: (BuildContext context) => BlocC(),
///         ),
///       ],
///       child: ChildA(),
///     ),
/// )
/// ```
///
/// to:
///
/// ```dart
/// MultiRepositoryProvider(
///   repositoryProviders: [
///     RepositoryProvider<RepositoryA>(create: (context) => RepositoryA()),
///     RepositoryProvider<RepositoryB>(create: (context) => RepositoryB()),
///     RepositoryProvider<RepositoryC>(create: (context) => RepositoryC()),
///   ],
///   providers: [
///     BlocProvider<BlocA>(create: (context) => BlocA()),
///     BlocProvider<BlocB>(create: (context) => BlocB()),
///     BlocProvider<BlocC>(create: (context) => BlocC()),
///   ],
///   child: ChildA(),
/// )
/// ```
///
/// [MultiProvider] converts the [RepositoryProvider] and [BlocProvider] lists 
/// into a tree of nested provider widgets.
/// As a result, the only advantage of using [MultiProvider] is
/// improved readability due to the reduction in nesting and boilerplate.
/// {@endtemplate}
class MultiProvider extends StatelessWidget {
  /// {@macro multi_provider}
  const MultiProvider({
    required this.repositoryProviders,
    required this.blocProviders,
    required this.child,
    super.key,
  });

  final List<RepositoryProvider<dynamic>> repositoryProviders;
  final List<BlocProvider> blocProviders;
  final Widget child;

  @override
  Widget build(BuildContext context) => MultiRepositoryProvider(
        providers: repositoryProviders,
        child: MultiBlocProvider(
          providers: blocProviders,
          child: child,
        ),
      );
}
