import "package:moxxyv2/xmpp/events.dart";
import "package:moxxyv2/xmpp/stringxml.dart";
import "package:moxxyv2/xmpp/managers/handlers.dart";
import "package:moxxyv2/xmpp/managers/attributes.dart";

import "package:logging/logging.dart";

abstract class XmppManagerBase {
  late final XmppManagerAttributes _managerAttributes;
  late final Logger _log;

  /// Registers the callbacks from [XmppConnection] with the manager
  void register(XmppManagerAttributes attributes) {
    _managerAttributes = attributes;
    _log = Logger(getName());
  }
  
  /// Returns the attributes that are registered with the manager.
  /// Must only be called after register has been called on it.
  XmppManagerAttributes getAttributes() {
    return _managerAttributes;
  }

  /// Return the [StanzaHandler]s associated with this manager that deal with stanzas we
  /// send.
  List<StanzaHandler> getOutgoingStanzaHandlers() => [];

  /// Return the [StanzaHandler]s associated with this manager that deal with stanzas we
  /// receive.
  List<StanzaHandler> getIncomingStanzaHandlers() => [];
  
  /// Return the [NonzaHandler]s associated with this manager.
  List<NonzaHandler> getNonzaHandlers() => [];

  /// Return a list of features that should be included in a disco response.
  List<String> getDiscoFeatures() => [];
  
  /// Return the Id (akin to xmlns) of this manager.
  String getId();

  /// Return a name that will be used for logging.
  String getName();

  /// Return the logger for this manager.
  Logger get logger => _log;
  
  /// Called when [XmppConnection] triggers an event
  void onXmppEvent(XmppEvent event) {}

  /// Runs all [NonzaHandler]s of this Manager which match the nonza. Resolves to true if
  /// the nonza has been handled by one of the handlers. Resolves to false otherwise.
  Future<bool> runNonzaHandlers(XMLNode nonza) async {
    bool handled = false;
    await Future.forEach(
      getNonzaHandlers(),
      (NonzaHandler handler) async {
        if (handler.matches(nonza)) {
          handled = true;
          await handler.callback(nonza);
        }
      }
    );

    return handled;
  }
}
