package ir.asparsa.hobbytaste.core.retrofit;

import ir.asparsa.android.core.logger.L;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import okio.BufferedSink;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action1;
import rx.subjects.PublishSubject;
import rx.subjects.SerializedSubject;
import rx.subjects.Subject;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

public class ProgressRequestBody extends RequestBody {
    private File mFile;

    private Subject<Integer, Integer> mOnUploadProgressSubject = new SerializedSubject<>(
            PublishSubject.<Integer>create());

    private static final int DEFAULT_BUFFER_SIZE = 2048;

    public ProgressRequestBody(
            final File file
    ) {
        mFile = file;
    }

    public ProgressRequestBody registerObserver(Action1<Integer> observer) {
        mOnUploadProgressSubject
                .onBackpressureDrop()
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(observer, new Action1<Throwable>() {
                    @Override public void call(Throwable throwable) {
                        L.w(ProgressRequestBody.class, "Error happened", throwable);
                    }
                });
        return this;
    }

    @Override
    public MediaType contentType() {
        // i want to upload only images
        return MediaType.parse("image/*");
    }

    @Override
    public long contentLength() throws IOException {
        return mFile.length();
    }

    @Override
    public void writeTo(BufferedSink sink) throws IOException {
        long fileLength = contentLength();
        byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
        FileInputStream in = new FileInputStream(mFile);
        long uploaded = 0;

        try {
            int read;
            int percentage = 0;
            int lastPercentage = 0;
            while ((read = in.read(buffer)) != -1) {

                // update progress on UI thread
                percentage = (int) (100 * uploaded / fileLength);
                if (percentage % 10 == 0 && percentage != lastPercentage) {
                    mOnUploadProgressSubject.onNext(percentage);
                    lastPercentage = percentage;
                }

                uploaded += read;
                sink.write(buffer, 0, read);
            }
        } finally {
            in.close();
            mOnUploadProgressSubject.onCompleted();
        }
    }
}

@@ -160,16 +160,38 @@
 edSink;%0A
+import rx.Observable;%0A
 import r
@@ -230,16 +230,16 @@
 dulers;%0A
-
 import r
@@ -259,16 +259,43 @@
 ction1;%0A
+import rx.functions.Func1;%0A
 import r
@@ -468,16 +468,54 @@
 ception;
+%0Aimport java.util.concurrent.TimeUnit;
 %0A%0Apublic
@@ -1026,13 +1026,286 @@
 sure
-Drop(
+Buffer()%0A                .concatMap(new Func1%3CInteger, Observable%3CInteger%3E%3E() %7B%0A                    @Override public Observable%3CInteger%3E call(Integer i) %7B%0A                        return Observable.just(i).delay(50, TimeUnit.MILLISECONDS);%0A                    %7D%0A                %7D
 )%0A  
@@ -2211,36 +2211,32 @@
   int percentage
- = 0
 ;%0A            in
@@ -2458,18 +2458,17 @@
 ntage %25 
-10
+5
  == 0 &&
@@ -2496,24 +2496,118 @@
 rcentage) %7B%0A
+                    L.i(ProgressRequestBody.class, %22The progress percentage: %22 + percentage);%0A
             

Make progress bar more smooth