package org.chenyang.http.impl.conn;

import org.chenyang.http.HttpException;
import org.chenyang.http.HttpHost;
import org.chenyang.http.HttpRequest;
import org.chenyang.http.ProtocolException;
import org.chenyang.http.annotation.Contract;
import org.chenyang.http.annotation.ThreadingBehavior;
import org.chenyang.http.client.config.RequestConfig;
import org.chenyang.http.client.protocol.HttpClientContext;
import org.chenyang.http.conn.SchemePortResolver;
import org.chenyang.http.conn.UnsupportedSchemeException;
import org.chenyang.http.conn.routing.HttpRoute;
import org.chenyang.http.conn.routing.HttpRoutePlanner;
import org.chenyang.http.protocol.HttpContext;
import org.chenyang.http.util.Args;
import java.net.InetAddress;

@Contract(
   threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL
)
public class DefaultRoutePlanner implements HttpRoutePlanner {
   private final SchemePortResolver schemePortResolver;

   public DefaultRoutePlanner(SchemePortResolver schemePortResolver) {
      this.schemePortResolver = (SchemePortResolver)(schemePortResolver != null ? schemePortResolver : DefaultSchemePortResolver.INSTANCE);
   }

   public HttpRoute determineRoute(HttpHost host, HttpRequest request, HttpContext context) throws HttpException {
      Args.notNull(request, "Request");
      if (host == null) {
         throw new ProtocolException("Target host is not specified");
      } else {
         HttpClientContext clientContext = HttpClientContext.adapt(context);
         RequestConfig config = clientContext.getRequestConfig();
         InetAddress local = config.getLocalAddress();
         HttpHost proxy = config.getProxy();
         if (proxy == null) {
            proxy = this.determineProxy(host, request, context);
         }

         HttpHost target;
         if (host.getPort() <= 0) {
            try {
               target = new HttpHost(host.getHostName(), this.schemePortResolver.resolve(host), host.getSchemeName());
            } catch (UnsupportedSchemeException ex) {
               throw new HttpException(ex.getMessage());
            }
         } else {
            target = host;
         }

         boolean secure = target.getSchemeName().equalsIgnoreCase("https");
         return proxy == null ? new HttpRoute(target, local, secure) : new HttpRoute(target, local, proxy, secure);
      }
   }

   protected HttpHost determineProxy(HttpHost target, HttpRequest request, HttpContext context) throws HttpException {
      return null;
   }
}
