package com.google.cloud.healthcare.imaging.dicomadapter.cstore.multipledest;

import com.google.cloud.healthcare.IDicomWebClient;
import com.google.cloud.healthcare.imaging.dicomadapter.AetDictionary;
import com.google.cloud.healthcare.imaging.dicomadapter.cstore.backup.BackupState;
import com.google.cloud.healthcare.imaging.dicomadapter.cstore.backup.IBackupUploadService;
import com.google.cloud.healthcare.imaging.dicomadapter.cstore.backup.IBackupUploader.BackupException;
import com.google.cloud.healthcare.imaging.dicomadapter.cstore.multipledest.sender.CStoreSender;
import com.google.cloud.healthcare.imaging.dicomadapter.cstore.multipledest.sender.CStoreSenderFactory;
import com.google.common.collect.ImmutableList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;

public class MultipleDestinationUploadService implements IMultipleDestinationUploadService {

  private Logger log = LoggerFactory.getLogger(MultipleDestinationUploadService.class);

  private CStoreSenderFactory cStoreSenderFactory;
  private IBackupUploadService backupUploadService;
  private int attemptsAmount;

  public MultipleDestinationUploadService(CStoreSenderFactory cStoreSenderFactory, IBackupUploadService backupUploadService, int attemptsAmount) {
    this.cStoreSenderFactory = cStoreSenderFactory;
    this.backupUploadService = backupUploadService;
    this.attemptsAmount = attemptsAmount;
  }

  @Override
  public void start(ImmutableList<IDicomWebClient> healthcareDestinations,
                    ImmutableList<AetDictionary.Aet> dicomDestinations,
                    InputStream inputStream,
                    String sopClassUID,
                    String sopInstanceUID) throws MultipleDestinationUploadServiceException {
    CStoreSender cStoreSender = cStoreSenderFactory.create();

    if (backupUploadService == null) {
      throw new IllegalArgumentException("backupUploadService is null. Some flags not set.");
    }

    List<Throwable> asyncUploadProcessingExceptions = new ArrayList<>();

    try {
      backupUploadService.createBackup(inputStream, sopInstanceUID);
    } catch (BackupException be) {
      log.error("{} processing failed.", this.getClass().getSimpleName(), be);
      throw new MultipleDestinationUploadServiceException(be);
    }

    List<CompletableFuture> uploadFutures = new ArrayList<>();

    CompletableFuture healthcareUploadFuture;
    for (IDicomWebClient healthcareDest: healthcareDestinations) {
      try {
        healthcareUploadFuture = backupUploadService.startUploading(
            healthcareDest,
            new BackupState(
                sopInstanceUID,
                attemptsAmount));

        uploadFutures.add(healthcareUploadFuture);
      } catch (BackupException be) {
        log.error("Async upload to healthcareDest task not started.", be);
        asyncUploadProcessingExceptions.add(be);
      }

    }

    CompletableFuture dicomUploadFuture;
    for (AetDictionary.Aet dicomDest: dicomDestinations) {
      try {
        dicomUploadFuture = backupUploadService.startUploading(
            cStoreSender,
            dicomDest,
            sopInstanceUID,
            sopClassUID,
            new BackupState(
                sopInstanceUID,
                attemptsAmount));

        uploadFutures.add(dicomUploadFuture);
      } catch (BackupException be) {
        log.error("Async upload to dicomDest task not started.", be);
        asyncUploadProcessingExceptions.add(be);
      }
    }

    for (CompletableFuture uploadFuture: uploadFutures) {
      try {
        uploadFuture.get();
      } catch (ExecutionException eex) {
        log.error("Exception on asyncUpload Job processing.", eex);
        asyncUploadProcessingExceptions.add(eex.getCause());
      } catch (InterruptedException ie) {
        log.error("CStoreSender task interrupted. Upload tasks canceled.", ie);
        Thread.currentThread().interrupt();
        throw new MultipleDestinationUploadServiceException(ie);
      }
    }

    if (asyncUploadProcessingExceptions.isEmpty()) {
      backupUploadService.removeBackup(sopInstanceUID);
    } else {
      log.error("Exception messages of the upload async jobs:\n{}",
          asyncUploadProcessingExceptions.stream().map(t -> t.getMessage()).collect(Collectors.joining("\n")));;

      throw new MultipleDestinationUploadServiceException(asyncUploadProcessingExceptions.get(0));
    }
  }
}

@@ -1947,71 +1947,8 @@
 n %7B%0A
-    CStoreSender cStoreSender = cStoreSenderFactory.create();%0A%0A
     
@@ -3026,24 +3026,139 @@
   %7D%0A%0A    %7D%0A%0A
+    if (dicomDestinations.isEmpty() == false) %7B%0A      CStoreSender cStoreSender = cStoreSenderFactory.create();%0A%0A  
     Completa
@@ -3186,24 +3186,26 @@
 Future;%0A    
+ 
+ 
 for (AetDict
@@ -3224,16 +3224,17 @@
 icomDest
+ 
 : dicomD
@@ -3240,32 +3240,34 @@
 Destinations) %7B%0A
+  
       try %7B%0A    
@@ -3266,24 +3266,26 @@
 y %7B%0A        
+  
 dicomUploadF
@@ -3283,32 +3283,46 @@
 omUploadFuture =
+%0A             
  backupUploadSer
@@ -3354,16 +3354,22 @@
         
+      
 cStoreSe
@@ -3382,24 +3382,30 @@
             
+      
 dicomDest,%0A 
@@ -3407,32 +3407,38 @@
 st,%0A            
+  
+    
 sopInstanceUID,%0A
@@ -3449,16 +3449,22 @@
         
+      
 sopClass
@@ -3472,32 +3472,38 @@
 ID,%0A            
+   
+   
 new BackupState(
@@ -3506,56 +3506,23 @@
 ate(
-%0A                sopInstanceUID,%0A               
+sopInstanceUID,
  att
@@ -3529,32 +3529,34 @@
 emptsAmount));%0A%0A
+  
         uploadFu
@@ -3583,32 +3583,34 @@
 dFuture);%0A      
+  
 %7D catch (BackupE
@@ -3624,32 +3624,34 @@
 n be) %7B%0A        
+ 
+ 
 log.error(%22Async
@@ -3696,32 +3696,34 @@
 %22, be);%0A        
+  
 asyncUploadProce
@@ -3739,32 +3739,42 @@
 ptions.add(be);%0A
+        %7D%0A
       %7D%0A    %7D%0A%0A 

check added: CStoreSender connection creation happens only on dicomDestinations is not Empty