package org.chenyang.http.client.protocol;

import org.chenyang.commons.logging.Log;
import org.chenyang.commons.logging.LogFactory;
import org.chenyang.http.Header;
import org.chenyang.http.HttpRequest;
import org.chenyang.http.HttpRequestInterceptor;
import org.chenyang.http.auth.AuthOption;
import org.chenyang.http.auth.AuthScheme;
import org.chenyang.http.auth.AuthState;
import org.chenyang.http.auth.AuthenticationException;
import org.chenyang.http.auth.ContextAwareAuthScheme;
import org.chenyang.http.auth.Credentials;
import org.chenyang.http.protocol.HttpContext;
import org.chenyang.http.util.Asserts;
import java.util.Queue;

/** @deprecated */
@Deprecated
abstract class RequestAuthenticationBase implements HttpRequestInterceptor {
   final Log log = LogFactory.getLog(this.getClass());

   public RequestAuthenticationBase() {
   }

   void process(AuthState authState, HttpRequest request, HttpContext context) {
      AuthScheme authScheme = authState.getAuthScheme();
      Credentials creds = authState.getCredentials();
      switch (authState.getState()) {
         case FAILURE:
            return;
         case SUCCESS:
            this.ensureAuthScheme(authScheme);
            if (authScheme.isConnectionBased()) {
               return;
            }
            break;
         case CHALLENGED:
            Queue<AuthOption> authOptions = authState.getAuthOptions();
            if (authOptions != null) {
               while(!authOptions.isEmpty()) {
                  AuthOption authOption = (AuthOption)authOptions.remove();
                  authScheme = authOption.getAuthScheme();
                  creds = authOption.getCredentials();
                  authState.update(authScheme, creds);
                  if (this.log.isDebugEnabled()) {
                     this.log.debug("Generating response to an authentication challenge using " + authScheme.getSchemeName() + " scheme");
                  }

                  try {
                     Header header = this.authenticate(authScheme, creds, request, context);
                     request.addHeader(header);
                     break;
                  } catch (AuthenticationException ex) {
                     if (this.log.isWarnEnabled()) {
                        this.log.warn(authScheme + " authentication error: " + ex.getMessage());
                     }
                  }
               }

               return;
            }

            this.ensureAuthScheme(authScheme);
      }

      if (authScheme != null) {
         try {
            Header header = this.authenticate(authScheme, creds, request, context);
            request.addHeader(header);
         } catch (AuthenticationException ex) {
            if (this.log.isErrorEnabled()) {
               this.log.error(authScheme + " authentication error: " + ex.getMessage());
            }
         }
      }

   }

   private void ensureAuthScheme(AuthScheme authScheme) {
      Asserts.notNull(authScheme, "Auth scheme");
   }

   private Header authenticate(AuthScheme authScheme, Credentials creds, HttpRequest request, HttpContext context) throws AuthenticationException {
      Asserts.notNull(authScheme, "Auth scheme");
      return authScheme instanceof ContextAwareAuthScheme ? ((ContextAwareAuthScheme)authScheme).authenticate(creds, request, context) : authScheme.authenticate(creds, request);
   }
}
