import 'package:flutter/foundation.dart';
import 'package:result_monad/result_monad.dart';

import '../globals.dart';
import '../models/auth/profile.dart';
import '../models/exec_error.dart';
import '../services/auth_service.dart';

class ActiveProfileSelector<T> extends ChangeNotifier {
  final _entries = <Profile, T>{};

  final T Function(Profile p)? _entryBuilder;

  final bool _subscribeAdded = false;

  ActiveProfileSelector(T Function(Profile p)? entryBuilder)
      : _entryBuilder = entryBuilder;

  void subscribeToProfileSwaps() {
    if (_subscribeAdded) {
      return;
    }

    getIt<AccountsService>().addListener(() {
      notifyListeners();
    });
  }

  bool get canCreateOnDemand => _entryBuilder != null;

  Result<T, ExecError> get activeEntry {
    final service = getIt<AccountsService>();
    if (!service.loggedIn) {
      return buildErrorResult(
        type: ErrorType.localError,
        message: 'No Logged In User',
      );
    }

    return getForProfile(service.currentProfile);
  }

  Result<T, ExecError> getForProfile(Profile p) {
    return runCatching(() {
      final entry = _entries.putIfAbsent(p, () => _buildNewEntry(p));
      return Result.ok(entry).execErrorCast();
    }).execErrorCast();
  }

  bool injectEntry(Profile p, T entry) {
    if (_entries.containsKey(p)) {
      return false;
    }
    _entries[p] = entry;
    return true;
  }

  T _buildNewEntry(Profile p) {
    final newEntry = _entryBuilder!(p);
    if (newEntry is ChangeNotifier) {
      newEntry.addListener(() {
        notifyListeners();
      });
    }

    return newEntry;
  }
}
