package org.chenyang.http.impl.client;

import org.chenyang.http.HttpConnection;
import org.chenyang.http.annotation.Contract;
import org.chenyang.http.annotation.ThreadingBehavior;
import org.chenyang.http.auth.AuthScheme;
import org.chenyang.http.auth.AuthState;
import org.chenyang.http.auth.Credentials;
import org.chenyang.http.client.UserTokenHandler;
import org.chenyang.http.client.protocol.HttpClientContext;
import org.chenyang.http.conn.ManagedHttpClientConnection;
import org.chenyang.http.protocol.HttpContext;
import java.security.Principal;
import javax.net.ssl.SSLSession;

@Contract(
   threading = ThreadingBehavior.IMMUTABLE
)
public class DefaultUserTokenHandler implements UserTokenHandler {
   public static final DefaultUserTokenHandler INSTANCE = new DefaultUserTokenHandler();

   public Object getUserToken(HttpContext context) {
      HttpClientContext clientContext = HttpClientContext.adapt(context);
      Principal userPrincipal = null;
      AuthState targetAuthState = clientContext.getTargetAuthState();
      if (targetAuthState != null) {
         userPrincipal = getAuthPrincipal(targetAuthState);
         if (userPrincipal == null) {
            AuthState proxyAuthState = clientContext.getProxyAuthState();
            userPrincipal = getAuthPrincipal(proxyAuthState);
         }
      }

      if (userPrincipal == null) {
         HttpConnection conn = clientContext.getConnection();
         if (conn.isOpen() && conn instanceof ManagedHttpClientConnection) {
            SSLSession sslsession = ((ManagedHttpClientConnection)conn).getSSLSession();
            if (sslsession != null) {
               userPrincipal = sslsession.getLocalPrincipal();
            }
         }
      }

      return userPrincipal;
   }

   private static Principal getAuthPrincipal(AuthState authState) {
      AuthScheme scheme = authState.getAuthScheme();
      if (scheme != null && scheme.isComplete() && scheme.isConnectionBased()) {
         Credentials creds = authState.getCredentials();
         if (creds != null) {
            return creds.getUserPrincipal();
         }
      }

      return null;
   }
}
