 			
 		}
 		
-	}
-	
-	func restoreFolder(for account: Account, folder: Folder, completion: @escaping (Result<Void, Error>) -> Void) {
-		account.addFolder(folder)
-		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 clearFolderRelationship(for feed: Feed, withFolderName folderName: String) {

			}
			
			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 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 {
			
