         }
     }
 
-    // MARK: UIImagePickerControlDelegate
-
+    // MARK: UITableViewDataSource
+
+    override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) ->
+        Bool {
+            return true
+    }
+
+    override func numberOfSections(in tableView: UITableView) -> Int {
+        return 1
+    }
+
+    override func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath,
+                            to destinationIndexPath: IndexPath) {
+        accounts.insert(accounts.remove(at: sourceIndexPath.row),
+                        at: destinationIndexPath.row)
+        persistAccountOrder()
+    }
+
+    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
+        return accounts.count
+    }
+
+    override func tableView(_ tableView: UITableView,
+                            cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+        let cell = tableView.dequeueReusableCell(withIdentifier: "AccountCell",
+                                                 for: indexPath) as! AccountCell
+        cell.account = accounts[indexPath.row]
+        cell.delegate = self
+        return cell
+    }
+
+    override func tableView(
+        _ tableView: UITableView,
+        commit editingStyle: UITableViewCell.EditingStyle,
+        forRowAt indexPath: IndexPath) {
+        if editingStyle == .delete {
+            let alertController = UIAlertController(
+                title: "Deleting This Account Will Not Turn Off Two-Factor Authentication",
+                message: "Please make sure two-factor authentication is turned off in the issuer's sett" +
+                "ings before deleting this account to prevent being locked out.",
+                preferredStyle: .actionSheet)
+
+            let deleteAccountAction = UIAlertAction(title: "Delete Account", style: .destructive) { _ in
+                self.deleteAccountForRowAtIndexPath(indexPath)
+            }
+
+            let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
+
+            alertController.addAction(deleteAccountAction)
+            alertController.addAction(cancelAction)
+
+            present(alertController, animated: true, completion: nil)
+        }
+    }
+
+    private func deleteAccountForRowAtIndexPath(_ indexPath: IndexPath) {
+        let account = self.accounts[indexPath.row]
+        guard self.keychain.deleteAccount(account) else {
+            presentTryAgainAlertWithTitle(
+                "Could Not Delete Account",
+                message: "An error occurred when deleting the account from the keychain.") {
+                    self.deleteAccountForRowAtIndexPath(indexPath)
+            }
+            return
+        }
+        accounts.remove(at: indexPath.row)
+        persistAccountOrder()
+        tableView.deleteRows(at: [indexPath], with: .automatic)
+        updateEditing()
+    }
+
+    // MARK: UITableViewDelegate
+
+    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
+        if tableView.isEditing {
+            tableView.deselectRow(at: indexPath, animated: true)
+
+            if let cell = tableView.cellForRow(at: indexPath) as? AccountCell {
+                performSegue(withIdentifier: "EditAccountSegue", sender: cell)
+            }
+        } else { // Not editing
+            if let cell = tableView.cellForRow(at: indexPath) {
+                guard let cellSuperview = cell.superview else {
+                    assertionFailure("The cell does not seem to be in the view hierarchy. How is that even possible!?")
+                    return
+                }
+
+                let menuController = UIMenuController.shared
+
+                // If you tap the same cell twice, this condition prevents the menu from being
+                // hidden and then instantly shown again causing an unpleasant flash.
+                //
+                // Since the cell could already be the first responder (from previously showing
+                // its menu and then scrolling the table view) and the menu could already be
+                // visible for another cell, we make sure to check both values.
+                if !(cell.isFirstResponder && menuController.isMenuVisible) {
+                    cell.becomeFirstResponder()
+
+                    menuController.setTargetRect(cell.frame, in: cellSuperview)
+                    menuController.setMenuVisible(true, animated: true)
+                }
+            }
+        }
+    }
+
+    override func tableView(_ tableView: UITableView,
+                            shouldShowMenuForRowAt indexPath: IndexPath) -> Bool {
+        return true
+    }
+
+    override func tableView(_ tableView: UITableView, canPerformAction action: Selector,
+                            forRowAt indexPath: IndexPath, withSender sender: Any?) -> Bool {
+        return action == #selector(copy(_:))
+    }
+
+    override func tableView(_ tableView: UITableView, performAction action: Selector,
+                            forRowAt indexPath: IndexPath, withSender sender: Any?) {
+        if action == #selector(copy(_:)) {
+            let cell = tableView.cellForRow(at: indexPath) as! AccountCell
+            cell.copy(self)
+        }
+    }
+}
+
+extension AccountsViewController: UISearchResultsUpdating {
+    func updateSearchResults(for searchController: UISearchController) {
+        let accountSearchResultsViewController = searchController.searchResultsController
+            as! AccountSearchResultsViewController
+        accountSearchResultsViewController.accounts = accounts.filter {
+            guard let string = searchController.searchBar.text else { return false }
+            return $0.description.range(of: string, options: .caseInsensitive, range: nil,
+                                        locale: nil) != nil
+        }
+    }
+}
+
+extension AccountsViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
     func imagePickerController(_ picker: UIImagePickerController,
                                didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
         dismiss(animated: true, completion: nil)


        self.createAccount(account)
    }

    // MARK: UITableViewDataSource

    override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) ->
        Bool {
            return true
    }

    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath,
                            to destinationIndexPath: IndexPath) {
        accounts.insert(accounts.remove(at: sourceIndexPath.row),
                        at: destinationIndexPath.row)
        persistAccountOrder()
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return accounts.count
    }

    override func tableView(_ tableView: UITableView,
                            cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "AccountCell",
                                                 for: indexPath) as! AccountCell
        cell.account = accounts[indexPath.row]
        cell.delegate = self
        return cell
    }

    override func tableView(
        _ tableView: UITableView,
        commit editingStyle: UITableViewCell.EditingStyle,
        forRowAt indexPath: IndexPath) {
        if editingStyle == .delete {
            let alertController = UIAlertController(
                title: "Deleting This Account Will Not Turn Off Two-Factor Authentication",
                message: "Please make sure two-factor authentication is turned off in the issuer's sett" +
                "ings before deleting this account to prevent being locked out.",
                preferredStyle: .actionSheet)

            let deleteAccountAction = UIAlertAction(title: "Delete Account", style: .destructive) { _ in
                self.deleteAccountForRowAtIndexPath(indexPath)
            }

            let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)

            alertController.addAction(deleteAccountAction)
            alertController.addAction(cancelAction)

            present(alertController, animated: true, completion: nil)
        }
    }

    private func deleteAccountForRowAtIndexPath(_ indexPath: IndexPath) {
        let account = self.accounts[indexPath.row]
        guard self.keychain.deleteAccount(account) else {
            presentTryAgainAlertWithTitle(
                "Could Not Delete Account",
                message: "An error occurred when deleting the account from the keychain.") {
                    self.deleteAccountForRowAtIndexPath(indexPath)
            }
            return
        }
        accounts.remove(at: indexPath.row)
        persistAccountOrder()
        tableView.deleteRows(at: [indexPath], with: .automatic)
        updateEditing()
    }

    // MARK: UITableViewDelegate

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        if tableView.isEditing {
            tableView.deselectRow(at: indexPath, animated: true)

            if let cell = tableView.cellForRow(at: indexPath) as? AccountCell {
                performSegue(withIdentifier: "EditAccountSegue", sender: cell)
            }
        } else { // Not editing
            if let cell = tableView.cellForRow(at: indexPath) {
                guard let cellSuperview = cell.superview else {
                    assertionFailure("The cell does not seem to be in the view hierarchy. How is that even possible!?")
                    return
                }

                let menuController = UIMenuController.shared

                // If you tap the same cell twice, this condition prevents the menu from being
                // hidden and then instantly shown again causing an unpleasant flash.
                //
                // Since the cell could already be the first responder (from previously showing
                // its menu and then scrolling the table view) and the menu could already be
                // visible for another cell, we make sure to check both values.
                if !(cell.isFirstResponder && menuController.isMenuVisible) {
                    cell.becomeFirstResponder()

                    menuController.setTargetRect(cell.frame, in: cellSuperview)
                    menuController.setMenuVisible(true, animated: true)
                }
            }
        }
    }

    override func tableView(_ tableView: UITableView,
                            shouldShowMenuForRowAt indexPath: IndexPath) -> Bool {
        return true
    }

    override func tableView(_ tableView: UITableView, canPerformAction action: Selector,
                            forRowAt indexPath: IndexPath, withSender sender: Any?) -> Bool {
        return action == #selector(copy(_:))
    }

    override func tableView(_ tableView: UITableView, performAction action: Selector,
                            forRowAt indexPath: IndexPath, withSender sender: Any?) {
        if action == #selector(copy(_:)) {
            let cell = tableView.cellForRow(at: indexPath) as! AccountCell
            cell.copy(self)
        }
    }
}

extension AccountsViewController: UISearchResultsUpdating {
    func updateSearchResults(for searchController: UISearchController) {
        let accountSearchResultsViewController = searchController.searchResultsController
            as! AccountSearchResultsViewController
        accountSearchResultsViewController.accounts = accounts.filter {
            guard let string = searchController.searchBar.text else { return false }
            return $0.description.range(of: string, options: .caseInsensitive, range: nil,
                                        locale: nil) != nil
        }
    }
}

extension AccountsViewController: AccountCreationDelegate {


private let accountOrderKey = "persistentRefs"

class AccountsViewController: UITableViewController {
    @IBOutlet weak var emptyView: UIView!

    private let keychain = Keychain()
