package com.google.sps.workspace;

import com.google.api.core.ApiFuture;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import com.google.sps.firebase.FirebaseAppManager;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

/**
 * Provides an interface to access and modify workspaces in the datastore. The contents of this
 * object will only reflect the current state of the entities. It will not update with the
 * datastore.
 */
public class Workspace {
  private final DatabaseReference reference;

  public Workspace(String studentUID, String TaUID)
      throws IOException, InterruptedException, ExecutionException {
    reference = FirebaseDatabase.getInstance(FirebaseAppManager.getApp()).getReference().push();

    ApiFuture<Void> studentFuture = reference.child("student").setValueAsync(studentUID);
    ApiFuture<Void> taFuture = reference.child("ta").setValueAsync(TaUID);

    studentFuture.get();
    taFuture.get();
  }

  public Workspace(String workspaceID) throws IOException {
    reference =
        FirebaseDatabase.getInstance(FirebaseAppManager.getApp()).getReference().child(workspaceID);
  }

  /** @return the studentUID */
  public Future<String> getStudentUID() {
    CompletableFuture<String> future = new CompletableFuture<>();

    reference
        .child("student")
        .addListenerForSingleValueEvent(
            new ValueEventListener() {

              @Override
              public void onDataChange(DataSnapshot snapshot) {
                future.complete((String) snapshot.getValue());
              }

              @Override
              public void onCancelled(DatabaseError error) {
                future.completeExceptionally(error.toException());
              }
            });

    return future;
  }

  /** @return the taUID */
  public Future<String> getTaUID() {
    CompletableFuture<String> future = new CompletableFuture<>();

    reference
        .child("ta")
        .addListenerForSingleValueEvent(
            new ValueEventListener() {

              @Override
              public void onDataChange(DataSnapshot snapshot) {
                future.complete((String) snapshot.getValue());
              }

              @Override
              public void onCancelled(DatabaseError error) {
                future.completeExceptionally(error.toException());
              }
            });

    return future;
  }

  public Future<List<String>> getFiles() {
    CompletableFuture<List<String>> future = new CompletableFuture<>();

    reference
        .child("files")
        .addListenerForSingleValueEvent(
            new ValueEventListener() {

              @Override
              public void onDataChange(DataSnapshot snapshot) {
                ArrayList<String> children = new ArrayList<>();
                for (DataSnapshot child : snapshot.getChildren()) {
                  children.add(child.getKey());
                }

                future.complete(children);
              }

              @Override
              public void onCancelled(DatabaseError error) {
                future.completeExceptionally(error.toException());
              }
            });

    return future;
  }

  /** @return the workspaceID */
  public String getWorkspaceID() {
    return reference.getKey();
  }
}

@@ -398,27 +398,93 @@
 java.io.
-IOException
+BufferedOutputStream;%0Aimport java.io.IOException;%0Aimport java.io.OutputStream
 ;%0Aimport
@@ -615,32 +615,32 @@
 utionException;%0A
-
 import java.util
@@ -658,16 +658,194 @@
 .Future;
+%0Aimport java.util.zip.GZIPOutputStream;%0Aimport org.apache.commons.compress.archivers.tar.TarArchiveEntry;%0Aimport org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
 %0A%0A/**%0A *
@@ -3019,22 +3019,29 @@
 re%3CList%3C
-String
+WorkspaceFile
 %3E%3E getFi
@@ -3075,22 +3075,29 @@
 re%3CList%3C
-String
+WorkspaceFile
 %3E%3E futur
@@ -3355,24 +3355,55 @@
     
-ArrayList%3CString
+try %7B%0A                  ArrayList%3CWorkspaceFile
 %3E ch
@@ -3426,24 +3426,26 @@
 ayList%3C%3E();%0A
+  
             
@@ -3518,16 +3518,18 @@
         
+  
 children
@@ -3537,21 +3537,31 @@
 add(
-child.getKey(
+new WorkspaceFile(child
 ));%0A
@@ -3568,35 +3568,39 @@
                 
+  
 %7D%0A%0A
+  
                 
@@ -3626,16 +3626,125 @@
 ldren);%0A
+                %7D catch (Exception e) %7B%0A                  future.completeExceptionally(e);%0A                %7D%0A
         
@@ -3953,32 +3953,684 @@
 rn future;%0A  %7D%0A%0A
+  public String getArchive(OutputStream out)%0A      throws InterruptedException, ExecutionException, IOException %7B%0A    List%3CWorkspaceFile%3E files = getFiles().get();%0A%0A    TarArchiveOutputStream tarOut =%0A        new TarArchiveOutputStream(new GZIPOutputStream(new BufferedOutputStream(out)));%0A%0A    for (WorkspaceFile file : files) %7B%0A      byte contents%5B%5D = file.getContents().get().getBytes();%0A%0A      TarArchiveEntry entry = new TarArchiveEntry(file.getFilename());%0A      entry.setSize(contents.length);%0A%0A      tarOut.putArchiveEntry(entry);%0A      tarOut.write(contents);%0A%0A      tarOut.closeArchiveEntry();%0A    %7D%0A%0A    tarOut.close();%0A%0A    return %22%22;%0A  %7D%0A%0A
   /** @return th

Add method to get an archive of the workspace.