import 'package:guru_utils/extensions/extensions.dart';

/// Created by Haoyi on 2023/1/26

abstract class IRemoteConfig {
  bool? getBool(String name, {bool? defaultValue});

  String? getString(String name, {String? defaultValue});

  double? getDouble(String name, {double? defaultValue});

  int? getInt(String name, {int? defaultValue});

  Stream<bool?> observeBool(String name, {bool? defaultValue});

  Stream<String?> observeString(String name, {String? defaultValue});

  Stream<double?> observeDouble(String name, {double? defaultValue});

  Stream<int?> observeInt(String name, {int? defaultValue});

  IRemoteConfig() {
    RemoteConfigUtils._remoteConfigSubject.addEx(this);
  }
}

class RemoteConfigUtils {
  static final BehaviorSubject<IRemoteConfig?> _remoteConfigSubject = BehaviorSubject.seeded(null);

  static Stream<IRemoteConfig> get observableRemoteConfig =>
      _remoteConfigSubject.stream.where((config) => config != null).cast<IRemoteConfig>();

  IRemoteConfig? get _remoteConfig => _remoteConfigSubject.value;

  static RemoteConfigUtils instance = RemoteConfigUtils._();

  RemoteConfigUtils._();

  bool? getBool(String name, {bool? defaultValue}) {
    return _remoteConfig?.getBool(name, defaultValue: defaultValue);
  }

  String? getString(String name, {String? defaultValue}) {
    return _remoteConfig?.getString(name, defaultValue: defaultValue);
  }

  double? getDouble(String name, {double? defaultValue}) {
    return _remoteConfig?.getDouble(name, defaultValue: defaultValue);
  }

  int? getInt(String name, {int? defaultValue}) {
    return _remoteConfig?.getInt(name, defaultValue: defaultValue);
  }

  Stream<bool?> observeBool(String name, {bool? defaultValue}) => observableRemoteConfig
      .flatMap((remoteConfig) => remoteConfig.observeBool(name, defaultValue: defaultValue));

  Stream<String?> observeString(String name, {String? defaultValue}) => observableRemoteConfig
      .flatMap((remoteConfig) => remoteConfig.observeString(name, defaultValue: defaultValue));

  Stream<double?> observeDouble(String name, {double? defaultValue}) => observableRemoteConfig
      .flatMap((remoteConfig) => remoteConfig.observeDouble(name, defaultValue: defaultValue));

  Stream<int?> observeInt(String name, {int? defaultValue}) => observableRemoteConfig
      .flatMap((remoteConfig) => remoteConfig.observeInt(name, defaultValue: defaultValue));
}
