/*
 * Copyright (c) 2015-present, Parse, LLC.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */
package com.parse;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import bolts.Task;

/**
 * Request returns a byte array of the response and provides a callback the progress of the data
 * read from the network.
 */
/** package */ class ParseAWSRequest extends ParseRequest<Void> {

  // The temp file is used to save the ParseFile content when we fetch it from server
  private final File tempFile;

  public ParseAWSRequest(ParseHttpRequest.Method method, String url, File tempFile) {
    super(method, url);
    this.tempFile = tempFile;
  }

  @Override
  protected Task<Void> onResponseAsync(ParseHttpResponse response,
      final ProgressCallback downloadProgressCallback) {
    int statusCode = response.getStatusCode();
    if (statusCode >= 200 && statusCode < 300 || statusCode == 304) {
      // OK
    } else {
      String action = method == ParseHttpRequest.Method.GET ? "Download from" : "Upload to";
      return Task.forError(new ParseException(ParseException.CONNECTION_FAILED, String.format(
        "%s S3 failed. %s", action, response.getReasonPhrase())));
    }

    if (method != ParseHttpRequest.Method.GET) {
      return null;
    }

    long totalSize = response.getTotalSize();
    int downloadedSize = 0;
    InputStream responseStream = null;
    try {
      responseStream = response.getContent();
      FileOutputStream tempFileStream = new FileOutputStream(tempFile);

      int nRead;
      byte[] data = new byte[32 << 10]; // 32KB

      while ((nRead = responseStream.read(data, 0, data.length)) != -1) {
        tempFileStream.write(data, 0, nRead);
        downloadedSize += nRead;
        if (downloadProgressCallback != null && totalSize != -1) {
          int progressToReport = Math.round((float) downloadedSize / (float) totalSize * 100.0f);
          downloadProgressCallback.done(progressToReport);
        }
      }
      return Task.forResult(null);
    } catch (IOException e) {
      return Task.forError(e);
    } finally {
      ParseIOUtils.closeQuietly(responseStream);
    }
  }
}

@@ -388,26 +388,26 @@
 ava.io.I
-OException
+nputStream
 ;%0Aimport
@@ -412,30 +412,40 @@
 rt java.
-io.InputStream
+util.concurrent.Callable
 ;%0A%0Aimpor
@@ -971,16 +971,22 @@
 seAsync(
+final 
 ParseHtt
@@ -1537,24 +1537,132 @@
 ull;%0A    %7D%0A%0A
+    return Task.call(new Callable%3CVoid%3E() %7B%0A      @Override%0A      public Void call() throws Exception %7B%0A    
     long tot
@@ -1691,24 +1691,28 @@
 otalSize();%0A
+    
     int down
@@ -1727,16 +1727,20 @@
 ze = 0;%0A
+    
     Inpu
@@ -1766,24 +1766,28 @@
 eam = null;%0A
+    
     try %7B%0A  
@@ -1780,24 +1780,28 @@
       try %7B%0A
+    
       respon
@@ -1840,16 +1840,20 @@
 ;%0A      
+ 
+   
 FileOutp
@@ -1913,24 +1913,28 @@
 le);%0A%0A      
+    
 int nRead;%0A 
@@ -1938,16 +1938,20 @@
 ;%0A      
+  
+  
 byte%5B%5D d
@@ -1985,16 +1985,20 @@
 / 32KB%0A%0A
+    
       wh
@@ -2071,16 +2071,20 @@
         
+  
+  
 tempFile
@@ -2113,32 +2113,36 @@
 nRead);%0A        
+    
 downloadedSize +
@@ -2154,24 +2154,28 @@
 ad;%0A        
+   
+ 
 if (download
@@ -2213,32 +2213,36 @@
 alSize != -1) %7B%0A
+    
           int pr
@@ -2323,16 +2323,20 @@
 00.0f);%0A
+    
         
@@ -2388,28 +2388,24 @@
 ort);%0A      
-  %7D%0A
       %7D%0A    
@@ -2410,98 +2410,41 @@
     
-return Task.forResult(null);%0A    %7D catch (IOException e) %7B%0A      return Task.forError(e);%0A
+    %7D%0A          return null;%0A    
     
@@ -2451,24 +2451,28 @@
 %7D finally %7B%0A
+    
       ParseI
@@ -2512,16 +2512,57 @@
 m);%0A    
-%7D
+    %7D%0A      %7D%0A    %7D, ParseExecutors.io());
 %0A  %7D%0A%7D%0A

Make ParseAWSRequest.onResponse run in io thread