//
//  This file is for XMPPStream and various internal components.
//

#import "XMPPStream.h"
#import "XMPPModule.h"

// Define the various states we'll use to track our progress
enum XMPPStreamState
{
	STATE_XMPP_DISCONNECTED,
	STATE_XMPP_RESOLVING_SRV,
	STATE_XMPP_CONNECTING,
	STATE_XMPP_OPENING,
	STATE_XMPP_NEGOTIATING,
	STATE_XMPP_STARTTLS_1,
	STATE_XMPP_STARTTLS_2,
	STATE_XMPP_POST_NEGOTIATION,
	STATE_XMPP_REGISTERING,
	STATE_XMPP_AUTH,
	STATE_XMPP_BINDING,
	STATE_XMPP_START_SESSION,
	STATE_XMPP_CONNECTED,
};
typedef enum XMPPStreamState XMPPStreamState;

/**
 * It is recommended that storage classes cache a stream's myJID.
 * This prevents them from constantly querying the property from the xmppStream instance,
 * as doing so goes through xmppStream's dispatch queue.
 * Caching the stream's myJID frees the dispatch queue to handle xmpp processing tasks.
 * 
 * The object of the notification will be the XMPPStream instance.
 * 
 * Note: We're not using the typical MulticastDelegate paradigm for this task as
 * storage classes are not typically added as a delegate of the xmppStream. 
**/
extern NSString *const XMPPStreamDidChangeMyJIDNotification;

@interface XMPPStream (/* Internal */)

/**
 * Categories on XMPPStream should maintain thread safety by dispatching through the internal xmppQueue.
 * They may also need to ensure the stream is in the proper state for their activity.
**/

@property (readonly) dispatch_queue_t xmppQueue;
@property (readonly) void *xmppQueueTag;
@property (readonly) XMPPStreamState state;

/**
 * This method is for use by xmpp authentication mechanism classes.
 * They should send elements using this method instead of the public sendElement classes,
 * as those methods don't send the elements while authentication is in progress.
**/
- (void)sendAuthElement:(NSXMLElement *)element;

/**
 * This method allows you to inject an element into the stream as if it was received on the socket.
 * This is an advanced technique, but makes for some interesting possibilities.
**/
- (void)injectElement:(NSXMLElement *)element;

@end

@interface XMPPModule (/* Internal */)

/**
 * Used internally by methods like XMPPStream's unregisterModule:.
 * Normally removing a delegate is a synchronous operation, but due to multiple dispatch_sync operations,
 * it must occasionally be done asynchronously to avoid deadlock.
**/
- (void)removeDelegate:(id)delegate delegateQueue:(dispatch_queue_t)delegateQueue synchronously:(BOOL)synchronously;

@end
