package org.wikipedia.dataclient.okhttp;

import android.net.Uri;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.RequiresApi;
import android.view.KeyEvent;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import org.apache.commons.lang3.StringUtils;
import org.wikipedia.WikipediaApp;
import org.wikipedia.dataclient.WikiSite;
import org.wikipedia.util.log.L;

import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import okhttp3.Headers;
import okhttp3.Request;
import okhttp3.Response;

public abstract class OkHttpWebViewClient extends WebViewClient {

    /*
    Note: Any data transformations performed here are only for the benefit of WebViews.
    They should not be made into general Interceptors.
    */

    private static final List<String> SUPPORTED_SCHEMES = Arrays.asList("http", "https");
    private static final String HEADER_CONTENT_TYPE = "content-type";
    private static final String HEADER_CONTENT_ENCODING = "content-encoding";
    private static final String CONTENT_TYPE_OGG = "application/ogg";

    @NonNull public abstract WikiSite getWikiSite();

    @SuppressWarnings("deprecation") @Override
    public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
        if (!SUPPORTED_SCHEMES.contains(Uri.parse(url).getScheme())) {
            return null;
        }

        try {
            Response rsp = request(url);
            return new WebResourceResponse(rsp.header(HEADER_CONTENT_TYPE),
                    rsp.header(HEADER_CONTENT_ENCODING), getInputStream(rsp));
        } catch (IOException e) {
            L.e(e);
        }
        return null;
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override public WebResourceResponse shouldInterceptRequest(WebView view,
                                                                WebResourceRequest request) {
        if (!SUPPORTED_SCHEMES.contains(request.getUrl().getScheme())) {
            return null;
        }

        try {
            Response rsp = request(request.getUrl().toString());
            return new WebResourceResponse(rsp.header(HEADER_CONTENT_TYPE),
                    rsp.header(HEADER_CONTENT_ENCODING), rsp.code(),
                    StringUtils.defaultIfBlank(rsp.message(), "Unknown error"),
                    toMap(rsp.headers()),
                    getInputStream(rsp));
        } catch (IOException e) {
            L.e(e);
        }
        return null;
    }

    @Override
    public boolean shouldOverrideKeyEvent(WebView view, KeyEvent event) {
        return ((event.isCtrlPressed() && event.getKeyCode() == KeyEvent.KEYCODE_F)
                || (!event.isCtrlPressed() && event.getKeyCode() == KeyEvent.KEYCODE_F3));
    }

    @NonNull private Response request(String url) throws IOException {
        return OkHttpConnectionFactory.getClient().newCall(new Request.Builder()
                .url(url)
                // TODO: Find a common way to set this header between here and RetrofitFactory.
                .header("Accept-Language", WikipediaApp.getInstance().getAcceptLanguage(getWikiSite()))
                .build())
                .execute();
    }

    @NonNull private Map<String, String> toMap(@NonNull Headers headers) {
        Map<String, String> map = new HashMap<>();
        for (int i = 0; i < headers.size(); ++i) {
            map.put(headers.name(i), headers.value(i));
        }
        return map;
    }

    @NonNull private InputStream getInputStream(@NonNull Response rsp) throws IOException {
        InputStream inputStream = rsp.body().byteStream();

        if (CONTENT_TYPE_OGG.equals(rsp.header(HEADER_CONTENT_TYPE))) {
            inputStream = new AvailableInputStream(rsp.body().byteStream(),
                    rsp.body().contentLength());
        }

        return inputStream;
    }
}

@@ -570,16 +570,49 @@
 Stream;%0A
+import java.nio.charset.Charset;%0A
 import j
@@ -628,16 +628,16 @@
 Arrays;%0A
-
 import j
@@ -1163,86 +1163,8 @@
 e%22;%0A
-    private static final String HEADER_CONTENT_ENCODING = %22content-encoding%22;%0A
     
@@ -1591,128 +1591,268 @@
     
-return new WebResourceResponse(rsp.header(HEADER_CONTENT_TYPE),%0A                    rsp.header(HEADER_CONTENT_ENCODING),
+// noinspection ConstantConditions%0A            return new WebResourceResponse(rsp.body().contentType().type() + %22/%22 + rsp.body().contentType().subtype(),%0A                    rsp.body().contentType().charset(Charset.defaultCharset()).name(),%0A                   
  get
@@ -1879,34 +1879,32 @@
        %7D catch (
-IO
 Exception e) %7B%0A 
@@ -2389,128 +2389,268 @@
     
-return new WebResourceResponse(rsp.header(HEADER_CONTENT_TYPE),%0A                    rsp.header(HEADER_CONTENT_ENCODING),
+// noinspection ConstantConditions%0A            return new WebResourceResponse(rsp.body().contentType().type() + %22/%22 + rsp.body().contentType().subtype(),%0A                    rsp.body().contentType().charset(Charset.defaultCharset()).name(),%0A                   
  rsp
@@ -2814,32 +2814,32 @@
 utStream(rsp));%0A
+
         %7D catch 
@@ -2839,18 +2839,16 @@
  catch (
-IO
 Exceptio

Fix interception of WebView content with extended content-type header.