/*
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.android.gnd.persistence.remote.firestore;

import android.net.Uri;
import com.google.android.gms.tasks.Task;
import com.google.android.gnd.persistence.remote.RemoteStorageManager;
import com.google.android.gnd.persistence.remote.TransferProgress;
import com.google.firebase.storage.StorageReference;
import io.reactivex.BackpressureStrategy;
import io.reactivex.Flowable;
import java.io.File;
import java8.util.StringJoiner;
import javax.inject.Inject;
import javax.inject.Singleton;

// TODO: Add column to Observation table for storing uploaded media urls
// TODO: Synced to remote db as well
@Singleton
public class FirestoreStorageManager implements RemoteStorageManager {

  // Top-level directory
  private static final String MEDIA_ROOT_DIR = "uploaded_media";

  @Inject StorageReference storageReference;

  @Inject
  FirestoreStorageManager() {}

  /**
   * Generates destination path for saving the image to Firestore Storage.
   *
   * <p>/uploaded_media/{project_id}/{form_id}/{feature_id}/{filename.jpg}
   */
  public static String getRemoteDestinationPath(
      String projectId, String formId, String featureId, String filename) {
    return new StringJoiner(File.separator)
        .add(MEDIA_ROOT_DIR)
        .add(projectId)
        .add(formId)
        .add(featureId)
        .add(filename)
        .toString();
  }

  private StorageReference createReference(String path) {
    return storageReference.child(path);
  }

  @Override
  public Task<Uri> getDownloadUrl(String remoteDestinationPath) {
    return createReference(remoteDestinationPath).getDownloadUrl();
  }

  @Override
  public Flowable<TransferProgress> uploadMediaFromFile(File file, String remoteDestinationPath) {
    return Flowable.create(
        emitter ->
            createReference(remoteDestinationPath)
                .putFile(Uri.fromFile(file))
                .addOnCompleteListener(uploadTask -> emitter.onComplete())
                .addOnPausedListener(taskSnapshot -> emitter.onNext(TransferProgress.paused()))
                .addOnFailureListener(emitter::onError)
                .addOnProgressListener(
                    taskSnapshot ->
                        emitter.onNext(
                            TransferProgress.inProgress(
                                (int) taskSnapshot.getTotalByteCount(),
                                (int) taskSnapshot.getBytesTransferred()))),
        BackpressureStrategy.LATEST);
  }
}

@@ -1091,16 +1091,42 @@
 ngleton;
+%0Aimport timber.log.Timber;
 %0A%0A// TOD
@@ -2526,42 +2526,247 @@
 ner(
-uploadTask -%3E emitter.onComplete()
+%0A                    uploadTask -%3E %7B%0A                      if (file.delete()) %7B%0A                        Timber.d(%22File deleted: %25s%22, file.getName());%0A                      %7D%0A                      emitter.onComplete();%0A                    %7D
 )%0A  

Delete local file after uploading to remote storage