package com.sobot.network.http.request;


import com.sobot.network.http.SobotOkHttpUtils;
import com.sobot.network.http.callback.Callback;
import com.sobot.network.http.model.SobotProgress;

import java.io.IOException;

import okhttp3.MediaType;
import okhttp3.RequestBody;
import okio.Buffer;
import okio.BufferedSink;
import okio.ForwardingSink;
import okio.Okio;
import okio.Sink;

/**
 * RequestBody 的包装类
 */
public class ProgressRequestBody extends RequestBody {

    private RequestBody requestBody;         //实际的待包装请求体
    private Callback callback;
    private UploadInterceptor interceptor;

    ProgressRequestBody(RequestBody requestBody, Callback callback) {
        this.requestBody = requestBody;
        this.callback = callback;
    }

    /** 重写调用实际的响应体的contentType */
    @Override
    public MediaType contentType() {
        return requestBody.contentType();
    }

    /** 重写调用实际的响应体的contentLength */
    @Override
    public long contentLength() {
        try {
            return requestBody.contentLength();
        } catch (IOException e) {
//            OkLogger.printStackTrace(e);
            return -1;
        }
    }

    /** 重写进行写入 */
    @Override
    public void writeTo(BufferedSink sink) throws IOException {
        CountingSink countingSink = new CountingSink(sink);
        BufferedSink bufferedSink = Okio.buffer(countingSink);
        requestBody.writeTo(bufferedSink);
        bufferedSink.flush();
    }

    /** 包装 */
    private final class CountingSink extends ForwardingSink {

        private SobotProgress progress;

        CountingSink(Sink delegate) {
            super(delegate);
            progress = new SobotProgress();
            progress.totalSize = contentLength();
        }

        @Override
        public void write(Buffer source, long byteCount) throws IOException {
            super.write(source, byteCount);

            SobotProgress.changeProgress(progress, byteCount, new SobotProgress.Action() {
                @Override
                public void call(SobotProgress progress) {
                    if (interceptor != null) {
                        interceptor.uploadProgress(progress);
                    } else {
                        onProgress(progress);
                    }
                }
            });
        }
    }

    private void onProgress(final SobotProgress progress) {
        SobotOkHttpUtils.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (callback != null) {
                    callback.inProgress(progress.fraction);
                }
            }
        });
    }

    public void setInterceptor(UploadInterceptor interceptor) {
        this.interceptor = interceptor;
    }

    public interface UploadInterceptor {
        void uploadProgress(SobotProgress progress);
    }
}
