 		
 	}
 	
-	private func processRestoredFeed(for account: Account, feed: Feed, editedName: String?, folder: Folder?, completion: @escaping (Result<Void, Error>) -> Void) {
+	func restoreFolder(for account: Account, folder: Folder, completion: @escaping (Result<Void, Error>) -> Void) {
+		
+		account.addFolder(folder)
+		let group = DispatchGroup()
+		
+		for feed in folder.topLevelFeeds {
+			
+			group.enter()
+			addFeed(for: account, to: folder, with: feed) { result in
+				if account.topLevelFeeds.contains(feed) {
+					account.removeFeed(feed)
+				}
+				group.leave()
+			}
+			
+		}
+		
+		group.notify(queue: DispatchQueue.main) {
+			completion(.success(()))
+		}
+		
+	}
+	
+	func accountDidInitialize(_ account: Account) {
+		credentials = try? account.retrieveBasicCredentials()
+		accountMetadata = account.metadata
+	}
+	
+	static func validateCredentials(transport: Transport, credentials: Credentials, completion: @escaping (Result<Bool, Error>) -> Void) {
+		
+		let caller = FeedbinAPICaller(transport: transport)
+		caller.credentials = credentials
+		caller.validateCredentials() { result in
+			DispatchQueue.main.async {
+				completion(result)
+			}
+		}
+		
+	}
+	
+}
+
+// MARK: Private
+
+private extension FeedbinAccountDelegate {
+	
+	func handleError(_ error: Error) {
+		// TODO: We should do a better job of error handling here.
+		// We need to prompt for credentials if they are expired.
+		#if os(macOS)
+		NSApplication.shared.presentError(error)
+		#else
+		UIApplication.shared.presentError(error)
+		#endif
+	}
+	
+	func refreshFolders(_ account: Account, completion: @escaping (Result<Void, Error>) -> Void) {
+		
+		caller.retrieveTags { [weak self] result in
+			switch result {
+			case .success(let tags):
+				BatchUpdate.shared.perform {
+					self?.syncFolders(account, tags)
+				}
+				self?.refreshFeeds(account, completion: completion)
+			case .failure(let error):
+				completion(.failure(error))
+			}
+		}
+		
+	}
+	
+	func syncFolders(_ account: Account, _ tags: [FeedbinTag]?) {
+		
+		guard let tags = tags else { return }
+
+		os_log(.debug, log: log, "Syncing folders with %ld tags.", tags.count)
+
+		let tagNames = tags.map { $0.name }
+
+		// Delete any folders not at Feedbin
+		if let folders = account.folders {
+			folders.forEach { folder in
+				if !tagNames.contains(folder.name ?? "") {
+					DispatchQueue.main.sync {
+						for feed in folder.topLevelFeeds {
+							account.addFeed(feed)
+							clearFolderRelationship(for: feed, withFolderName: folder.name ?? "")
+						}
+						account.deleteFolder(folder)
+					}
+				}
+			}
+		}
+		
+		let folderNames: [String] =  {
+			if let folders = account.folders {
+				return folders.map { $0.name ?? "" }
+			} else {
+				return [String]()
+			}
+		}()
+
+		// Make any folders Feedbin has, but we don't
+		tagNames.forEach { tagName in
+			if !folderNames.contains(tagName) {
+				DispatchQueue.main.sync {
+					_ = account.ensureFolder(with: tagName)
+				}
+			}
+		}
+		
+	}
+	
+	func refreshFeeds(_ account: Account, completion: @escaping (Result<Void, Error>) -> Void) {
+		
+		caller.retrieveSubscriptions { [weak self] result in
+			switch result {
+			case .success(let subscriptions):
+				
+				self?.caller.retrieveTaggings { [weak self] result in
+					switch result {
+					case .success(let taggings):
+						
+						self?.caller.retrieveIcons { [weak self] result in
+							switch result {
+							case .success(let icons):
+
+								BatchUpdate.shared.perform {
+									self?.syncFeeds(account, subscriptions)
+									self?.syncTaggings(account, taggings)
+									self?.syncFavicons(account, icons)
+								}
+
+								completion(.success(()))
+								
+							case .failure(let error):
+								completion(.failure(error))
+							}
+							
+						}
+						
+					case .failure(let error):
+						completion(.failure(error))
+					}
+					
+				}
+				
+			case .failure(let error):
+				completion(.failure(error))
+			}
+			
+		}
+		
+	}
+
+	func syncFeeds(_ account: Account, _ subscriptions: [FeedbinSubscription]?) {
+		
+		guard let subscriptions = subscriptions else { return }
+		
+		os_log(.debug, log: log, "Syncing feeds with %ld subscriptions.", subscriptions.count)
+		
+		let subFeedIds = subscriptions.map { String($0.feedID) }
+		
+		// Remove any feeds that are no longer in the subscriptions
+		if let folders = account.folders {
+			for folder in folders {
+				for feed in folder.topLevelFeeds {
+					if !subFeedIds.contains(feed.feedID) {
+						DispatchQueue.main.sync {
+							folder.removeFeed(feed)
+						}
+					}
+				}
+			}
+		}
+		
+		for feed in account.topLevelFeeds {
+			if !subFeedIds.contains(feed.feedID) {
+				DispatchQueue.main.sync {
+					account.removeFeed(feed)
+				}
+			}
+		}
+		
+		// Add any feeds we don't have and update any we do
+		subscriptions.forEach { subscription in
+			
+			let subFeedId = String(subscription.feedID)
+			
+			DispatchQueue.main.sync {
+				if let feed = account.idToFeedDictionary[subFeedId] {
+					feed.name = subscription.name
+					feed.homePageURL = subscription.homePageURL
+				} else {
+					let feed = account.createFeed(with: subscription.name, url: subscription.url, feedID: subFeedId, homePageURL: subscription.homePageURL)
+					feed.subscriptionID = String(subscription.subscriptionID)
+					account.addFeed(feed)
+				}
+			}
+			
+		}
+		
+	}
+
+	func syncTaggings(_ account: Account, _ taggings: [FeedbinTagging]?) {
+		
+		guard let taggings = taggings else { return }
+
+		os_log(.debug, log: log, "Syncing taggings with %ld taggings.", taggings.count)
+		
+		// Set up some structures to make syncing easier
+		let folderDict: [String: Folder] = {
+			if let folders = account.folders {
+				return Dictionary(uniqueKeysWithValues: folders.map { ($0.name ?? "", $0) } )
+			} else {
+				return [String: Folder]()
+			}
+		}()
+
+		let taggingsDict = taggings.reduce([String: [FeedbinTagging]]()) { (dict, tagging) in
+			var taggedFeeds = dict
+			if var taggedFeed = taggedFeeds[tagging.name] {
+				taggedFeed.append(tagging)
+				taggedFeeds[tagging.name] = taggedFeed
+			} else {
+				taggedFeeds[tagging.name] = [tagging]
+			}
+			return taggedFeeds
+		}
+
+		// Sync the folders
+		for (folderName, groupedTaggings) in taggingsDict {
+			
+			guard let folder = folderDict[folderName] else { return }
+			
+			let taggingFeedIDs = groupedTaggings.map { String($0.feedID) }
+			
+			// Move any feeds not in the folder to the account
+			for feed in folder.topLevelFeeds {
+				if !taggingFeedIDs.contains(feed.feedID) {
+					DispatchQueue.main.sync {
+						folder.removeFeed(feed)
+						clearFolderRelationship(for: feed, withFolderName: folder.name ?? "")
+						account.addFeed(feed)
+					}
+				}
+			}
+			
+			// Add any feeds not in the folder
+			let folderFeedIds = folder.topLevelFeeds.map { $0.feedID }
+			
+			for tagging in groupedTaggings {
+				let taggingFeedID = String(tagging.feedID)
+				if !folderFeedIds.contains(taggingFeedID) {
+					guard let feed = account.idToFeedDictionary[taggingFeedID] else {
+						continue
+					}
+					DispatchQueue.main.sync {
+						saveFolderRelationship(for: feed, withFolderName: folderName, id: String(tagging.taggingID))
+						folder.addFeed(feed)
+					}
+				}
+			}
+			
+		}
+		
+		let taggedFeedIDs = Set(taggings.map { String($0.feedID) })
+		
+		// Remove all feeds from the account container that have a tag
+		DispatchQueue.main.sync {
+			for feed in account.topLevelFeeds {
+				if taggedFeedIDs.contains(feed.feedID) {
+					account.removeFeed(feed)
+				}
+			}
+		}
+
+	}
+	
+	func syncFavicons(_ account: Account, _ icons: [FeedbinIcon]?) {
+		
+		guard let icons = icons else { return }
+		
+		os_log(.debug, log: log, "Syncing favicons with %ld icons.", icons.count)
+		
+		let iconDict = Dictionary(uniqueKeysWithValues: icons.map { ($0.host, $0.url) } )
+		
+		for feed in account.flattenedFeeds() {
+			for (key, value) in iconDict {
+				if feed.homePageURL?.contains(key) ?? false {
+					DispatchQueue.main.sync {
+						feed.faviconURL = value
+					}
+					break
+				}
+			}
+		}
+
+	}
+	
+	func processRestoredFeed(for account: Account, feed: Feed, editedName: String?, folder: Folder?, completion: @escaping (Result<Void, Error>) -> Void) {
 		
 		if let folder = folder {
 			

			}
			
			processRestoredFeedName(for: account, feed: feed, editedName: editedName!, completion: completion)

		}
		
	}
	
	private func processRestoredFeedName(for account: Account, feed: Feed, editedName: String, completion: @escaping (Result<Void, Error>) -> Void) {
		
		renameFeed(for: account, with: feed, to: editedName) { result in
			switch result {

			
		}
		
	}
	
	func clearFolderRelationship(for feed: Feed, withFolderName folderName: String) {
