package com.google.job.data;

import com.google.api.core.ApiFunction;
import com.google.api.core.ApiFuture;
import com.google.api.core.ApiFutures;
import com.google.cloud.firestore.DocumentReference;
import com.google.cloud.firestore.DocumentSnapshot;
import com.google.cloud.firestore.Firestore;
import com.google.cloud.firestore.WriteResult;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.firestore.FireStoreUtils;
import org.checkerframework.checker.nullness.compatqual.NullableDecl;

import java.util.Optional;
import java.util.concurrent.Future;

/** Helps persist and retrieve job posts. */
public final class JobsDatabase {
    private static final String JOB_COLLECTION = "Jobs";

//    private final Firestore firestore;
//
//    public JobsDatabase(Firestore firestore) {
//        this.firestore = firestore;
//    }

    /**
     * Adds a newly created job post.
     *
     * @param newJob Newly created job post. Assumes that it is non-nullable.
     * @return Future for the added job post task, convenient for testing.
     */
    public Future<DocumentReference> addJob(Job newJob) {
        return FireStoreUtils.getFireStore()
                .collection(JOB_COLLECTION)
                .add(newJob);
    }

    /**
     * Edits the job post.
     *
     * @param jobId Id for the target job post in the database.
     * @param job Updated job post.
     * @return A future of the detailed information of the update.
     */
    public Future<WriteResult> setJob(String jobId, Job job) {
        // Overwrites the whole job post
        return FireStoreUtils.getFireStore()
                .collection(JOB_COLLECTION).document(jobId)
                .set(job);
    }

    /**
     * Fetches the snapshot future of a specific job post.
     *
     * @param jobId Id for the job post in the database.
     * @return Future of the target job post.
     */
    public Future<Optional<Job>> fetchJob(String jobId) {
        DocumentReference docRef = FireStoreUtils.getFireStore()
                .collection(JOB_COLLECTION).document(jobId);

        // Asynchronously retrieves the document
        ApiFuture<DocumentSnapshot> snapshotFuture = docRef.get();

        ApiFunction<DocumentSnapshot, Optional<Job>> jobFunction = new ApiFunction<DocumentSnapshot, Optional<Job>>() {
            @NullableDecl
            public Optional<Job> apply(@NullableDecl DocumentSnapshot documentSnapshot) {
                return FireStoreUtils.convertDocumentSnapshotToPOJO(documentSnapshot, Job.class);
            }
        };

        return ApiFutures.transform(snapshotFuture, jobFunction, MoreExecutors.directExecutor());
    }
}

@@ -178,169 +178,9 @@
 ore.
-DocumentReference;%0Aimport com.google.cloud.firestore.DocumentSnapshot;%0Aimport com.google.cloud.firestore.Firestore;%0Aimport com.google.cloud.firestore.WriteResult
+*
 ;%0Aim
@@ -410,16 +410,66 @@
 .Future;
+%0Aimport java.util.concurrent.atomic.AtomicBoolean;
 %0A%0A/** He
@@ -603,148 +603,8 @@
 %22;%0A%0A
-//    private final Firestore firestore;%0A//%0A//    public JobsDatabase(Firestore firestore) %7B%0A//        this.firestore = firestore;%0A//    %7D%0A%0A
     
@@ -1206,16 +1206,82 @@
 update.%0A
+     * @throws IllegalArgumentException If the job id is invalid.%0A
      */%0A
@@ -1340,16 +1340,48 @@
 Job job)
+ throws IllegalArgumentException
  %7B%0A     
@@ -1416,38 +1416,58 @@
 ob post%0A        
-return
+DocumentReference docRef =
  FireStoreUtils.
@@ -1480,33 +1480,16 @@
 eStore()
-%0A                
 .collect
@@ -1523,16 +1523,17 @@
 t(jobId)
+;
 %0A       
@@ -1533,24 +1533,152 @@
         
-        
+if (!isDocumentExist(docRef)) %7B%0A            throw new IllegalArgumentException(%22Job Id does not exist%22);%0A        %7D%0A        return docRef
 .set(job
@@ -1860,24 +1860,90 @@
 t job post.%0A
+     * @throws IllegalArgumentException If the job id is invalid.%0A
      */%0A    
@@ -1993,16 +1993,48 @@
 g jobId)
+ throws IllegalArgumentException
  %7B%0A     
@@ -2151,24 +2151,148 @@
 nt(jobId);%0A%0A
+        if (!isDocumentExist(docRef)) %7B%0A            throw new IllegalArgumentException(%22Job Id does not exist%22);%0A        %7D%0A%0A
         // A
@@ -2859,11 +2859,295 @@
 );%0A    %7D
+%0A%0A    private boolean isDocumentExist(DocumentReference docIdRef) %7B%0A        AtomicBoolean isExist = new AtomicBoolean(/* initialValue= */false);%0A        docIdRef.addSnapshotListener((documentSnapshot, e) -%3E isExist.set(documentSnapshot.exists()));%0A%0A        return isExist.get();%0A    %7D
 %0A%7D%0A

Add security check for job id