Files
nirvana-ios/nirvana-ios/Repositories/FirestoreService.swift
T

216 lines
9.4 KiB
Swift

//
// FirestoreService.swift
// nirvana-ios
//
// Created by Arjun Patel on 12/18/21.
//
import Foundation
import Firebase
import FirebaseCore
import FirebaseFirestore
import FirebaseFirestoreSwift
class FirestoreService {
enum Collection: String {
case users = "users"
case messages = "messages"
case userFriends = "user_friends" // associating a user to
case convos = "convos"
}
private var db = Firestore.firestore()
func getUserRealtime(userId: String, completion: @escaping((_ user: User?) -> ())) {
db.collection(Collection.users.rawValue).document(userId).addSnapshotListener { documentSnapshot, error in
guard let document = documentSnapshot else {
print("Error fetching getting user realtime listener: \(error!)")
completion(nil)
return
}
DispatchQueue.main.async {
guard let updatedOrNewUser = try? document.data(as: User.self)
else {
completion(nil)
print("Document data was empty. tried fetching updated user document in firestore service")
return
}
// up to date user
completion(updatedOrNewUser)
}
}
}
func getUser(userId: String, completion: @escaping((_ user: User?) -> ())) {
let docRef = db.collection(Collection.users.rawValue).document(userId)
docRef.getDocument { (document, error) in
if let document = document, document.exists {
let returnedUser = try? document.data(as: User.self)
completion(returnedUser)
} else {
print("user doesn't exist")
completion(nil)
}
}
}
func getUserByPhoneNumber(phoneNumber: String, completion: @escaping((_ user: User?) -> ())) {
// TODO: validation here as well to verify that phone number string is even valid
db.collection(Collection.users.rawValue).whereField("phoneNumber", isEqualTo: phoneNumber)
.getDocuments() { (querySnapshot, err) in
if let err = err {
print("Error getting documents: \(err)")
completion(nil)
} else {
if !(querySnapshot?.isEmpty)! {
for document in querySnapshot!.documents {
let returnedUser = try? document.data(as: User.self)
completion(returnedUser)
}
} else {
completion(nil)
}
}
}
}
func createUser(user: User, completion: @escaping((_ state: ServiceState) -> ())) {
do {
let _ = try db.collection(Collection.users.rawValue).document(user.id!).setData(from: user)
completion(ServiceState.success("user created"))
} catch {
print("error in updating user \(error.localizedDescription)")
completion(ServiceState.error(ServiceError(description: error.localizedDescription)))
}
}
func updateUser(user: User, completion: @escaping((_ state: ServiceState) -> ())) {
do {
if user.id != nil {
let _ = try db.collection(Collection.users.rawValue).document(user.id!).setData(from: user)
completion(ServiceState.success("Updated user in firestore service"))
} else {
completion(ServiceState.error(ServiceError(description: "No user id given to firestore service")))
}
} catch {
print("error in updating user \(error.localizedDescription)")
completion(ServiceState.error(ServiceError(description: error.localizedDescription)))
}
}
func getCollectionRef(_ collectionName: Collection) -> CollectionReference {
return db.collection(collectionName.rawValue)
}
func getFirestoreServerTimestamp() -> FieldValue {
return FieldValue.serverTimestamp()
}
func createOrUpdateUserFriends(userFriend: UserFriends, activateOrDeactivate: Bool, completion: @escaping((_ state: ServiceState) -> ())) {
do {
let userFriendCollection = db.collection(Collection.userFriends.rawValue)
// get the userFriend based on...if not exists, then update
let userFriendDocRef = userFriendCollection.whereField("userId", isEqualTo: userFriend.userId).whereField("friendId", isEqualTo: userFriend.friendId)
userFriendDocRef.getDocuments() { (querySnapshot, err) in
if let err = err {
print("error in trying to check if user friend relationship exists \(err.localizedDescription)")
completion(ServiceState.error(ServiceError(description: err.localizedDescription)))
} else {
// TODO: there shoudn't be multiple, see if this would cause issues
if querySnapshot!.documents.isEmpty { //not existing already, create one
let _ = try? userFriendCollection.addDocument(from: userFriend)
print("created new user friend! no existing relationship")
completion(ServiceState.success("created userfriend in firestore service"))
}
else { // there seems to be something existing
for document in querySnapshot!.documents {
// update this userFriend that is existing
let _ = try? userFriendCollection.document(document.documentID).setData(["isActive": activateOrDeactivate, "lastUpdatedTimestamp": self.getFirestoreServerTimestamp()], merge:true)
print("already existing, just updated")
completion(ServiceState.success("updated userfriend in firestore service"))
}
}
}
}
} catch {
print("error in creating user friend \(error.localizedDescription)")
completion(ServiceState.error(ServiceError(description: error.localizedDescription)))
}
}
func createMessage(message: Message, completion: @escaping((_ state: ServiceState) -> ())) {
do {
let _ = try db.collection(Collection.messages.rawValue).addDocument(from: message)
completion(ServiceState.success("message created"))
} catch {
print("error in creating message \(error.localizedDescription)")
completion(ServiceState.error(ServiceError(description: error.localizedDescription)))
}
}
}
// updates to user
extension FirestoreService {
func updateUserDeviceToken(userId: String, deviceToken: String, completion: @escaping((_ state: ServiceState) -> ())) {
do {
if userId != nil {
let _ = try db.collection(Collection.users.rawValue).document(userId).setData(["deviceToken": deviceToken], merge: true)
completion(ServiceState.success("Updated user device token"))
} else {
completion(ServiceState.error(ServiceError(description: "No user id given to firestore service")))
}
} catch {
print("error in updating user \(error.localizedDescription)")
completion(ServiceState.error(ServiceError(description: error.localizedDescription)))
}
}
func updateUserStatus(userId: String, userStatus: UserStatus, completion: @escaping((_ state: ServiceState) -> ())) {
do {
let _ = try db.collection(Collection.users.rawValue).document(userId).setData(["userStatus": userStatus.rawValue, "lastUpdatedStatusTimestamp": getFirestoreServerTimestamp()], merge: true)
completion(ServiceState.success("Updated user status"))
} catch {
print("error in updating user \(error.localizedDescription)")
completion(ServiceState.error(ServiceError(description: error.localizedDescription)))
}
}
}
// convos
extension FirestoreService {
func createConvo(convo: Convo, completion: @escaping((_ state: ServiceState) -> ())) {
do {
let _ = try db.collection(Collection.convos.rawValue).addDocument(from: convo)
completion(ServiceState.success("convo created"))
} catch {
print("error in creating convo \(error.localizedDescription)")
completion(ServiceState.error(ServiceError(description: error.localizedDescription)))
}
}
func updateConvo(convo: Convo, completion: @escaping((_ state: ServiceState) -> ())) {
do {
if convo.id != nil {
let _ = try db.collection(Collection.convos.rawValue).document(convo.id!).setData(from: convo)
completion(ServiceState.success("Updated convo in firestore service"))
} else {
completion(ServiceState.error(ServiceError(description: "No convo id given to firestore service")))
}
} catch {
print("error in updating convo \(error.localizedDescription)")
completion(ServiceState.error(ServiceError(description: error.localizedDescription)))
}
}
}