package me.devsaki.hentoid.util;

import androidx.annotation.Nullable;

import com.android.volley.AuthFailureError;
import com.android.volley.Header;
import com.android.volley.Request;
import com.android.volley.toolbox.BaseHttpStack;
import com.android.volley.toolbox.HttpResponse;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import okhttp3.Call;
import okhttp3.Headers;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;

/**
 * Created by Robb_w in 2018/04; heavily inspired by
 *      https://gist.github.com/LOG-TAG/3ad1c191b3ca7eab3ea6834386e30eb9
 *     and
 *      https://gist.github.com/JakeWharton/5616899
 *  <p>
 *  okhttp wrapper for Volley; allows the use of okhttp as low-level network operations handler by Volley
 *  The main reason being okhttp's ability to automatically follow 301 & 302's while default Volley handler cannot
 */
public class VolleyOkHttp3Stack extends BaseHttpStack {

    private final OkHttpClient client;

    public VolleyOkHttp3Stack(int timeoutMs) {
        client = OkHttpClientSingleton.getInstance(timeoutMs);
    }

    private static void setConnectionParametersForRequest(okhttp3.Request.Builder builder, Request<?> request)
            throws AuthFailureError {
        switch (request.getMethod()) {
            case Request.Method.DEPRECATED_GET_OR_POST:
                // Ensure backwards compatibility.  Volley assumes a request with a null body is a GET.
                byte[] postBody = request.getBody();
                if (postBody != null) {
                    builder.post(RequestBody.create(MediaType.parse(request.getBodyContentType()), postBody));
                }
                break;
            case Request.Method.GET:
                builder.get();
                break;
            case Request.Method.DELETE:
                builder.delete(createRequestBody(request));
                break;
            case Request.Method.POST:
                builder.post(createRequestBody(request));
                break;
            case Request.Method.PUT:
                builder.put(createRequestBody(request));
                break;
            case Request.Method.HEAD:
                builder.head();
                break;
            case Request.Method.OPTIONS:
                builder.method("OPTIONS", null);
                break;
            case Request.Method.TRACE:
                builder.method("TRACE", null);
                break;
            case Request.Method.PATCH:
                builder.patch(createRequestBody(request));
                break;
            default:
                throw new IllegalStateException("Unknown method type.");
        }
    }

    @Nullable
    private static RequestBody createRequestBody(Request r) throws AuthFailureError {
        final byte[] body = r.getBody();
        if (body == null) {
            return null;
        }
        return RequestBody.create(MediaType.parse(r.getBodyContentType()), body);
    }

    @Override
    public HttpResponse executeRequest(Request<?> request, Map<String, String> additionalHeaders) throws IOException, AuthFailureError {
        okhttp3.Request.Builder okHttpRequestBuilder = new okhttp3.Request.Builder();
        okHttpRequestBuilder.url(request.getUrl());

        Map<String, String> headers = request.getHeaders();
        for (final String name : headers.keySet()) {
            okHttpRequestBuilder.addHeader(name, headers.get(name));
        }
        for (final String name : additionalHeaders.keySet()) {
            okHttpRequestBuilder.addHeader(name, additionalHeaders.get(name));
        }

        setConnectionParametersForRequest(okHttpRequestBuilder, request);

        okhttp3.Request okHttpRequest = okHttpRequestBuilder.build();
        Call okHttpCall = client.newCall(okHttpRequest);
        Response okHttpResponse = okHttpCall.execute();


        int code = okHttpResponse.code();
        ResponseBody body = okHttpResponse.body();
        InputStream content = body == null ? null : body.byteStream();
        int contentLength = body == null ? 0 : (int) body.contentLength();
        List<Header> responseHeaders = mapHeaders(okHttpResponse.headers());
        return new HttpResponse(code, responseHeaders, contentLength, content);
    }

    private List<Header> mapHeaders(Headers responseHeaders) {
        List<Header> headers = new ArrayList<>();
        for (int i = 0, len = responseHeaders.size(); i < len; i++) {
            final String name = responseHeaders.name(i);
            final String value = responseHeaders.value(i);
            if (name != null) {
                headers.add(new Header(name, value));
            }
        }
        return headers;
    }
}



@@ -648,21 +648,16 @@
 ed by%0A *
-     
  https:/
@@ -720,24 +720,15 @@
 9%0A *
-    
  and%0A *
-     
  htt
@@ -774,17 +774,15 @@
 9%0A *
- 
  %3Cp%3E%0A *
- 
  okh
@@ -882,17 +882,16 @@
 olley%0A *
- 
  The mai
@@ -2968,30 +2968,16 @@
 == null)
- %7B%0A           
  return 
@@ -2982,26 +2982,16 @@
 n null;%0A
-        %7D%0A
         
@@ -3434,33 +3434,47 @@
    for (
-final String name
+Map.Entry%3CString, String%3E entry
  : heade
@@ -3472,26 +3472,28 @@
 y : headers.
-k
 e
+ntr
 ySet()) %7B%0A  
@@ -3482,32 +3482,111 @@
 s.entrySet()) %7B%0A
+            String value = (null == entry.getValue()) ? %22%22 : entry.getValue();%0A
             okHt
@@ -3616,31 +3616,29 @@
 der(
-name, headers.get(name)
+entry.getKey(), value
 );%0A 
@@ -3659,33 +3659,47 @@
    for (
-final String name
+Map.Entry%3CString, String%3E entry
  : addit
@@ -3711,18 +3711,20 @@
 Headers.
-k
 e
+ntr
 ySet()) 
@@ -3717,32 +3717,111 @@
 s.entrySet()) %7B%0A
+            String value = (null == entry.getValue()) ? %22%22 : entry.getValue();%0A
             okHt
@@ -3851,41 +3851,29 @@
 der(
-name, additionalHeaders.get(name)
+entry.getKey(), value
 );%0A 
@@ -4141,17 +4141,16 @@
 ute();%0A%0A
-%0A
         
@@ -4847,44 +4847,8 @@
 i);%0A
-            if (name != null) %7B%0A    
     
@@ -4893,30 +4893,16 @@
 alue));%0A
-            %7D%0A
         

Make Sonar happy