#ifndef _SEC_SOSENGINE_H_
#define _SEC_SOSENGINE_H_
#include "keychain/SecureObjectSync/SOSDataSource.h"
#include "keychain/SecureObjectSync/SOSMessage.h"
#include "keychain/SecureObjectSync/SOSPeer.h"
#include <dispatch/dispatch.h>
__BEGIN_DECLS
typedef void (^SOSEnginePeerMessageSentBlock)(bool success);
typedef struct {
__unsafe_unretained SOSEnginePeerMessageSentBlock block;
SOSEngineRef engine;
SOSPeerRef peer;
SOSCoderRef coder;
SOSManifestRef local;
SOSManifestRef proposed;
SOSManifestRef confirmed;
SOSMessageRef message;
} SOSEnginePeerMessageSentCallback;
void SOSEngineMessageCallCallback(SOSEnginePeerMessageSentCallback *sent, bool ok);
void SOSEngineMessageCallbackSetCallback(SOSEnginePeerMessageSentCallback *sent, SOSEnginePeerMessageSentBlock block);
SOSEngineRef SOSEngineCreate(SOSDataSourceRef dataSource, CFErrorRef *error);
SOSManifestRef SOSEngineCopyManifest(SOSEngineRef engine, CFErrorRef *error);
SOSManifestRef SOSEngineCopyLocalPeerManifest(SOSEngineRef engine, SOSPeerRef peer, CFErrorRef *error);
SOSManifestRef SOSEngineCopyLocalPeerManifest_locked(SOSEngineRef engine, SOSPeerRef peer, CFErrorRef *error);
bool SOSEngineUpdateChanges(SOSEngineRef engine, SOSDataSourceTransactionSource source, CFArrayRef changes, CFErrorRef *error);
void SOSEngineAddManifest(SOSEngineRef engine, SOSManifestRef manifest);
SOSManifestRef SOSEngineGetManifestForDigest(SOSEngineRef engine, CFDataRef digest);
CFDataRef SOSEnginePatchRecordAndCopyDigest(SOSEngineRef engine, SOSManifestRef base, SOSManifestRef removals, SOSManifestRef additions, CFErrorRef *error);
SOSManifestRef SOSEngineCopyPersistedManifest(SOSEngineRef engine, CFDictionaryRef persisted, CFStringRef key);
CFMutableArrayRef SOSEngineCopyPersistedManifestArray(SOSEngineRef engine, CFDictionaryRef persisted, CFStringRef key, CFErrorRef *error);
void SOSEngineClearCache(SOSEngineRef engine);
void SOSEngineDispose(SOSEngineRef engine);
bool SOSEngineHandleMessage(SOSEngineRef engine, CFStringRef peerID,
CFDataRef message, CFErrorRef *error);
void SOSEngineCircleChanged(SOSEngineRef engine, CFStringRef myPeerID, CFArrayRef trustedPeers, CFArrayRef untrustedPeers);
void SOSEngineForEachPeer(SOSEngineRef engine, void (^with)(SOSPeerRef peer));
CF_RETURNS_RETAINED CFSetRef SOSEngineSyncWithBackupPeers(SOSEngineRef engine, CFSetRef peers, bool forceReset, CFErrorRef *error);
bool SOSEngineHandleMessage_locked(SOSEngineRef engine, CFStringRef peerID, SOSMessageRef message,
SOSTransactionRef txn, bool *commit, bool *somethingChanged, CFErrorRef *error);
CFDataRef SOSEngineCreateMessage_locked(SOSEngineRef engine, SOSTransactionRef txn, SOSPeerRef peer,
CFMutableArrayRef *attributeList, CFErrorRef *error, SOSEnginePeerMessageSentCallback **sentCallback);
void SOSEngineFreeMessageCallback(SOSEnginePeerMessageSentCallback* sentCallback);
SOSPeerRef SOSEngineCopyPeerWithID(SOSEngineRef engine, CFStringRef peer_id, CFErrorRef *error);
bool SOSEngineForPeerID(SOSEngineRef engine, CFStringRef peer_id, CFErrorRef *error, void (^forPeer)(SOSTransactionRef txn, SOSPeerRef peer));
bool SOSEngineWithPeerID(SOSEngineRef engine, CFStringRef peer_id, CFErrorRef *error, void (^with)(SOSPeerRef peer, SOSCoderRef coder, SOSDataSourceRef dataSource, SOSTransactionRef txn, bool *forceSaveState));
bool SOSEngineInitializePeerCoder(SOSEngineRef engine, SOSFullPeerInfoRef myPeerInfo, SOSPeerInfoRef peerInfo, CFErrorRef *error);
CFDataRef SOSEngineCreateMessageToSyncToPeer(SOSEngineRef engine, CFStringRef peerID, CFMutableArrayRef *attributeList, SOSEnginePeerMessageSentCallback **sentBlock, CFErrorRef *error);
CFStringRef SOSEngineGetMyID(SOSEngineRef engine);
bool SOSEnginePeerDidConnect(SOSEngineRef engine, CFStringRef peerID, CFErrorRef *error);
bool SOSEngineSetPeerConfirmedManifest(SOSEngineRef engine, CFStringRef backupName,
CFDataRef keybagDigest, CFDataRef manifestData, CFErrorRef *error);
CFArrayRef SOSEngineCopyBackupPeerNames(SOSEngineRef engine, CFErrorRef *error);
CFStringRef SOSEngineEnsureCopyBackupPeerForView(SOSEngineRef engine, CFStringRef backupPeerID, CFErrorRef *error);
void logRawMessage(CFDataRef message, bool sending, uint64_t seqno);
CFArrayRef SOSEngineGetPeerIDs(SOSEngineRef engine);
CFArrayRef SOSEngineCopyPeerConfirmedDigests(SOSEngineRef engine, CFErrorRef *error);
SOSDataSourceRef SOSEngineGetDataSource(SOSEngineRef engine);
bool SOSTestEngineSaveWithDER(SOSEngineRef engine, CFDataRef derState, CFErrorRef *error);
bool SOSTestEngineSave(SOSEngineRef engine, SOSTransactionRef txn, CFErrorRef *error);
bool SOSTestEngineLoad(SOSEngineRef engine, SOSTransactionRef txn, CFErrorRef *error);
CFMutableDictionaryRef derStateToDictionaryCopy(CFDataRef state, CFErrorRef *error);
bool SOSTestEngineSaveCoders(CFTypeRef engine, SOSTransactionRef txn, CFErrorRef *error);
bool TestSOSEngineLoadCoders(CFTypeRef engine, SOSTransactionRef txn, CFErrorRef *error);
void TestSOSEngineDoOnQueue(CFTypeRef engine, dispatch_block_t action);
bool TestSOSEngineDoTxnOnQueue(CFTypeRef engine, CFErrorRef *error, void(^transaction)(SOSTransactionRef txn, bool *commit));
CFMutableDictionaryRef TestSOSEngineGetCoders(CFTypeRef engine);
typedef void (^SOSEnginePeerInSyncBlock)(CFStringRef peerID, CFSetRef views);
void SOSEngineSetSyncCompleteListener(SOSEngineRef engine, SOSEnginePeerInSyncBlock notify_block);
void SOSEngineSetSyncCompleteListenerQueue(SOSEngineRef engine, dispatch_queue_t notify_queue);
void SOSEngineLogState(SOSEngineRef engine);
extern CFStringRef kSOSEngineStatev2;
extern CFStringRef kSOSEnginePeerStates;
extern CFStringRef kSOSEngineManifestCache;
#define kSOSEngineProtectionDomainClassD kSecAttrAccessibleAlwaysPrivate
extern CFStringRef kSOSEngineCoders;
#define kSOSEngineProtectionDomainClassA kSecAttrAccessibleWhenUnlockedThisDeviceOnly
bool SOSEngineGetCodersNeedSaving(SOSEngineRef engine);
void SOSEngineSetCodersNeedSaving(SOSEngineRef engine, bool saved);
extern CFStringRef kSOSEngineStateVersionKey;
__END_DECLS
#endif