import 'package:rxdart/subjects.dart';
import 'package:krezus/repositories/json/json_repository.dart';
import 'package:krezus/repositories/metadata/models/budget.dart';
import 'package:krezus/repositories/metadata/models/category.dart';
import 'package:krezus/repositories/metadata/models/account.dart';
import 'package:krezus/repositories/metadata/models/metadata.dart';
import 'package:krezus/repositories/metadata/models/settings.dart';

class MetadataRepository {

  final JsonRepository _jsonRepository;
  final _categoriesController = BehaviorSubject<List<Category>>.seeded(const []);
  final _budgetController = BehaviorSubject<List<Budget>>.seeded(const []);
  final _accountController = BehaviorSubject<List<Account>>.seeded(const []);
  final _settingsController = BehaviorSubject<Settings>.seeded(const Settings());

  MetadataRepository({
    required jsonRepository,
  }) : _jsonRepository = jsonRepository;

  List<Category> getCategories() {
    return _categoriesController.value;
  }

  Stream<List<Category>> getCategoriesStream() {
    return _categoriesController.asBroadcastStream();
  }

  List<Budget> getBudgets() {
    return _budgetController.value;
  }

  Stream<List<Budget>> getBudgetsStream() {
    return _budgetController.asBroadcastStream();
  }

  List<Account> getAccounts() {
    return _accountController.value;
  }

  Stream<List<Account>> getAccountsStream() {
    return _accountController.asBroadcastStream();
  }

  Settings getSettings() {
    return _settingsController.value;
  }

  Stream<Settings> getSettingsStream() {
    return _settingsController.asBroadcastStream();
  }

  void loadMetadata() async {
    Metadata metadata = await _jsonRepository.loadJson(Metadata(), MetadataFactory());
    _broadcastMetadata(metadata);
  }

  List<Category> saveCategories(List<Category> categories) {
    Metadata metadata = _constructMetadataFromControllers();
    metadata.categories = categories;
    _jsonRepository.saveJson(metadata);
    _categoriesController.add(categories);
    return categories;
  }

  List<Budget> saveBudgets(List<Budget> budgets) {
    Metadata metadata = _constructMetadataFromControllers();
    metadata.budgets = budgets;
    _jsonRepository.saveJson(metadata);
    _budgetController.add(budgets);
    return budgets;
  }

  List<Account> saveAccounts(List<Account> accounts) {
    Metadata metadata = _constructMetadataFromControllers();
    metadata.accounts = accounts;
    _jsonRepository.saveJson(metadata);
    _accountController.add(accounts);
    return accounts;
  }

  Settings saveSettings(Settings settings) {
    Metadata metadata = _constructMetadataFromControllers();
    metadata.settings = settings;
    _jsonRepository.saveJson(metadata);
    _settingsController.add(settings);
    return settings;
  }

  void deleteMetadata() {
    Metadata metadata = Metadata();
    _jsonRepository.saveJson(metadata);
    _broadcastMetadata(metadata);
  }

  void _broadcastMetadata(Metadata metadata) {
    _categoriesController.add(metadata.categories);
    _budgetController.add(metadata.budgets);
    _accountController.add(metadata.accounts);
    _settingsController.add(metadata.settings);
  }

  Metadata _constructMetadataFromControllers() {
    return Metadata(
      categories: _categoriesController.value,
      budgets: _budgetController.value,
      accounts: _accountController.value,
      settings: _settingsController.value,
    );
  }
}