/*
 * Copyright 2007 Yusuke Yamamoto
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package twitter4j.internal.http.alternative;

import java.io.IOException;
import java.net.Authenticator;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.PasswordAuthentication;
import java.net.Proxy;
import java.net.URL;
import java.security.GeneralSecurityException;

import javax.net.ssl.SSLContext;

import twitter4j.internal.http.HttpClientConfiguration;
import twitter4j.internal.http.HttpResponseCode;
import twitter4j.internal.logging.Logger;
import twitter4j.internal.util.z_T4JInternalStringUtil;

import com.squareup.okhttp.ConnectionPool;
import com.squareup.okhttp.OkHttpClient;

/**
 * @author Hiroaki Takeuchi - takke30 at gmail.com
 * @since Twitter4J 3.x.x
 */
public class HttpClientImpl extends twitter4j.internal.http.HttpClientImpl implements HttpResponseCode, java.io.Serializable {
    private static final Logger logger = Logger.getLogger(HttpClientImpl.class);

    private static final int MAX_IDLE_CONNECTIONS = 5;

    private static final long KEEP_ALIVE_DURATION_MS = 300;

    public static boolean sPreferSpdy = true;

    private OkHttpClient client = null;
    
    public HttpClientImpl() {
        super();
    }

    public HttpClientImpl(HttpClientConfiguration conf) {
        super(conf);
    }
    
    protected HttpURLConnection getConnection(String url) throws IOException {
        if (!sPreferSpdy) {
            return super.getConnection(url);
        }
        
        prepareClient();
        
        HttpURLConnection con;
        if (isProxyConfigured()) {
            if (CONF.getHttpProxyUser() != null && !CONF.getHttpProxyUser().equals("")) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Proxy AuthUser: " + CONF.getHttpProxyUser());
                    logger.debug("Proxy AuthPassword: " + z_T4JInternalStringUtil.maskString(CONF.getHttpProxyPassword()));
                }
                Authenticator.setDefault(new Authenticator() {
                    @Override
                    protected PasswordAuthentication
                    getPasswordAuthentication() {
                        //respond only to proxy auth requests
                        if (getRequestorType().equals(RequestorType.PROXY)) {
                            return new PasswordAuthentication(CONF.getHttpProxyUser(),
                                    CONF.getHttpProxyPassword().toCharArray());
                        } else {
                            return null;
                        }
                    }
                });
            }
            final Proxy proxy = new Proxy(Proxy.Type.HTTP, InetSocketAddress
                    .createUnresolved(CONF.getHttpProxyHost(), CONF.getHttpProxyPort()));
            if (logger.isDebugEnabled()) {
                logger.debug("Opening proxied connection(" + CONF.getHttpProxyHost() + ":" + CONF.getHttpProxyPort() + ")");
            }
            client.setProxy(proxy);
        }
        con = client.open(new URL(url));
        
        if (CONF.getHttpConnectionTimeout() > 0) {
            con.setConnectTimeout(CONF.getHttpConnectionTimeout());
        }
        if (CONF.getHttpReadTimeout() > 0) {
            con.setReadTimeout(CONF.getHttpReadTimeout());
        }
        con.setInstanceFollowRedirects(false);
        return con;
    }

    private void prepareClient() {
        
        if (client == null) {
            client = new OkHttpClient();
            
            // if not set connection-pool, 
            // it used the default pool invalidly that is disabled the keep-alive feature for TFJ-296.
            client.setConnectionPool(new ConnectionPool(MAX_IDLE_CONNECTIONS, KEEP_ALIVE_DURATION_MS));
            
            // to avoid the crash default to using a single global SSL context.
            // see https://github.com/square/okhttp/issues/184#issuecomment-18772733
            SSLContext sslContext;
            try {
                sslContext = SSLContext.getInstance("TLS");
                sslContext.init(null, null, null);
            } catch (GeneralSecurityException e) {
                throw new AssertionError(); // The system has no TLS. Just give up.
            }
            client.setSslSocketFactory(sslContext.getSocketFactory());
        }
    }
}

@@ -934,16 +934,51 @@
 ntext;%0A%0A
+import twitter4j.TwitterException;%0A
 import t
@@ -1021,24 +1021,113 @@
 figuration;%0A
+import twitter4j.internal.http.HttpRequest;%0Aimport twitter4j.internal.http.HttpResponse;%0A
 import twitt
@@ -1840,24 +1840,73 @@
 ient = null;
+%0A%0A    private String lastRequestTransport = null;
 %0A    %0A    pu
@@ -4089,24 +4089,431 @@
  con;%0A    %7D%0A
+    %0A    @Override%0A    public HttpResponse request(HttpRequest req) throws TwitterException %7B%0A        HttpResponse res = super.request(req);%0A        %0A        if (res != null) %7B%0A            lastRequestTransport = res.getResponseHeader(%22OkHttp-Selected-Transport%22);%0A        %7D%0A        %0A        return res;%0A    %7D%0A    %0A    public String getLastRequestTransport() %7B%0A        return lastRequestTransport;%0A    %7D%0A    
 %0A    private

save the transport header 'OkHttp-Selected-Transport' of the last request