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.*;
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;
import java.util.concurrent.atomic.AtomicBoolean;

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

    /**
     * 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.
     * @throws IllegalArgumentException If the job id is invalid.
     */
    public Future<WriteResult> setJob(String jobId, Job job) throws IllegalArgumentException {
        // Overwrites the whole job post
        DocumentReference docRef = FireStoreUtils.getFireStore().collection(JOB_COLLECTION).document(jobId);
        if (!isDocumentExist(docRef)) {
            throw new IllegalArgumentException("Job Id does not exist");
        }
        return docRef.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.
     * @throws IllegalArgumentException If the job id is invalid.
     */
    public Future<Optional<Job>> fetchJob(String jobId) throws IllegalArgumentException {
        DocumentReference docRef = FireStoreUtils.getFireStore()
                .collection(JOB_COLLECTION).document(jobId);

        if (!isDocumentExist(docRef)) {
            throw new IllegalArgumentException("Job Id does not exist");
        }

        // 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());
    }

    private boolean isDocumentExist(DocumentReference docIdRef) {
        AtomicBoolean isExist = new AtomicBoolean(/* initialValue= */false);
        docIdRef.addSnapshotListener((documentSnapshot, e) -> isExist.set(documentSnapshot.exists()));

        return isExist.get();
    }
}

@@ -414,58 +414,8 @@
 ure;
-%0Aimport java.util.concurrent.atomic.AtomicBoolean;
 %0A%0A/*
@@ -1378,34 +1378,14 @@
     
-DocumentReference docRef =
+return
  Fir
@@ -1410,16 +1410,33 @@
 eStore()
+%0A                
 .collect
@@ -1470,17 +1470,16 @@
 t(jobId)
-;
 %0A       
@@ -1483,144 +1483,16 @@
     
-if (!isDocumentExist(docRef)) %7B%0A            throw new IllegalArgumentException(%22Job Id does not exist%22);%0A        %7D%0A        return docRef
+        
 .set
@@ -1977,132 +1977,8 @@
 );%0A%0A
-        if (!isDocumentExist(docRef)) %7B%0A            throw new IllegalArgumentException(%22Job Id does not exist%22);%0A        %7D%0A%0A
     
@@ -2450,16 +2450,16 @@
     %7D;%0A%0A
+
         
@@ -2557,291 +2557,7 @@
    %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

Remove the id check part; leave it until servlet