public EmbeddableDatabaseChanges(EmbeddableDocumentStore embeddableDocumentStore, Action onDispose, Func<string, Etag, string[], bool> tryResolveConflictByUsingRegisteredConflictListeners)
		{
			this.onDispose = onDispose;
			this.tryResolveConflictByUsingRegisteredConflictListeners = tryResolveConflictByUsingRegisteredConflictListeners;
			Task = new CompletedTask<IDatabaseChanges>(this);
			indexesObservable = new EmbeddableObservableWithTask<IndexChangeNotification>();
			documentsObservable = new EmbeddableObservableWithTask<DocumentChangeNotification>();
			bulkInsertObservable = new EmbeddableObservableWithTask<BulkInsertChangeNotification>();
			replicationConflictsObservable = new EmbeddableObservableWithTask<ReplicationConflictNotification>();

			embeddableDocumentStore.DocumentDatabase.TransportState.OnIndexChangeNotification += (o, notification) =>
				enqueuedActions.Add(() => indexesObservable.Notify(o, notification));
			embeddableDocumentStore.DocumentDatabase.TransportState.OnDocumentChangeNotification += (o, notification) =>
				 enqueuedActions.Add(() => documentsObservable.Notify(o, notification));
			embeddableDocumentStore.DocumentDatabase.TransportState.OnReplicationConflictNotification += (o, notification) =>
				 enqueuedActions.Add(() => replicationConflictsObservable.Notify(o, notification));
			embeddableDocumentStore.DocumentDatabase.TransportState.OnReplicationConflictNotification += TryResolveConflict;
			embeddableDocumentStore.DocumentDatabase.TransportState.OnBulkInsertChangeNotification += (o, notification) =>
			                                                                                          enqueuedActions.Add(() =>
			                                                                                          {
				                                                                                          bulkInsertObservable.Notify(o, notification);
																										  documentsObservable.Notify(o, notification);
			                                                                                          });

			enqueuedTask = System.Threading.Tasks.Task.Factory.StartNew(() =>
			{
				while (true)
				{
					var action = enqueuedActions.Take();
					if (action == null)
						return;
					action();
				}
			});
		}
		public EmbeddableDatabaseChanges(EmbeddableDocumentStore embeddableDocumentStore, Action onDispose)
		{
			this.onDispose = onDispose;
			Task = new CompletedTask();
			indexesObservable = new EmbeddableObserableWithTask<IndexChangeNotification>();
			documentsObservable = new EmbeddableObserableWithTask<DocumentChangeNotification>();

			embeddableDocumentStore.DocumentDatabase.TransportState.OnIndexChangeNotification += indexesObservable.Notify;
			embeddableDocumentStore.DocumentDatabase.TransportState.OnDocumentChangeNotification += documentsObservable.Notify;
		}
		public EmbeddableDatabaseChanges(EmbeddableDocumentStore embeddableDocumentStore, Action onDispose)
		{
			this.onDispose = onDispose;
			Task = new CompletedTask<IDatabaseChanges>(this);
			indexesObservable = new EmbeddableObservableWithTask<IndexChangeNotification>();
			documentsObservable = new EmbeddableObservableWithTask<DocumentChangeNotification>();

			embeddableDocumentStore.DocumentDatabase.TransportState.OnIndexChangeNotification += (o, notification) => 
				enqueuedActions.Add(() => indexesObservable.Notify(o, notification));
			embeddableDocumentStore.DocumentDatabase.TransportState.OnDocumentChangeNotification += (o, notification) =>
				 enqueuedActions.Add(() => documentsObservable.Notify(o, notification));

			enqueuedTask = System.Threading.Tasks.Task.Factory.StartNew(() =>
			{
				while (true)
				{
					var action = enqueuedActions.Take();
					if (action == null)
						return;
					action();
				}
			});
		}
		private Task<Action<HttpWebRequest>> DoOAuthRequestAsync(string oauthSource, string serverRsaExponent, string serverRsaModulus, string challenge, int tries)
		{
			if (oauthSource == null) throw new ArgumentNullException("oauthSource");

			var authRequestTuple = PrepareOAuthRequest(oauthSource, serverRsaExponent, serverRsaModulus, challenge);
			var authRequest = authRequestTuple.Item1;

			Task sendDataTask = new CompletedTask();
			if (authRequestTuple.Item2 != null)
			{
				sendDataTask = Task<Stream>.Factory.FromAsync(authRequest.BeginGetRequestStream, authRequest.EndGetRequestStream, null).ContinueWith(task =>
				{
					using (var stream = task.Result)
					using (var writer = new StreamWriter(stream))
					{
						writer.Write(authRequestTuple.Item2);
					}
				});
			}


			return sendDataTask.ContinueWith(t =>
			{
				t.AssertNotFailed();

				return Task<WebResponse>.Factory.FromAsync(authRequest.BeginGetResponse, authRequest.EndGetResponse, null)
					.AddUrlIfFaulting(authRequest.RequestUri)
					.ConvertSecurityExceptionToServerNotFound()
					.ContinueWith(task =>
					{
						try
						{
							using (var stream = task.Result.GetResponseStreamWithHttpDecompression())
							using (var reader = new StreamReader(stream))
							{
								CurrentOauthToken = "Bearer " + reader.ReadToEnd();
								return
									CompletedTask.With(
										(Action<HttpWebRequest>)(request => SetHeader(request.Headers, "Authorization", CurrentOauthToken)));
							}
						}
						catch (AggregateException ae)
						{
							var ex = ae.ExtractSingleInnerException() as WebException;

							if (tries > 2 || ex == null)
								// We've already tried three times and failed
								throw;



							var authResponse = ex.Response as HttpWebResponse;
							if (authResponse == null || authResponse.StatusCode != HttpStatusCode.PreconditionFailed)
								throw;

							var header = authResponse.Headers["Www-Authenticate"];
							if (string.IsNullOrEmpty(header) || !header.StartsWith(OAuthHelper.Keys.WWWAuthenticateHeaderKey))
								throw;

							authResponse.Close();

							var challengeDictionary =
								OAuthHelper.ParseDictionary(header.Substring(OAuthHelper.Keys.WWWAuthenticateHeaderKey.Length).Trim());

							return DoOAuthRequestAsync(oauthSource,
													   challengeDictionary.GetOrDefault(OAuthHelper.Keys.RSAExponent),
													   challengeDictionary.GetOrDefault(OAuthHelper.Keys.RSAModulus),
													   challengeDictionary.GetOrDefault(OAuthHelper.Keys.Challenge),
													   tries + 1);
						}
					}).Unwrap();
			}).Unwrap();
		}