/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.knox.gateway.dispatch;

import java.io.IOException;
import java.security.KeyStore;
import java.security.Principal;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import javax.net.ssl.SSLContext;
import javax.servlet.FilterConfig;

import org.apache.http.ssl.SSLContextBuilder;
import org.apache.knox.gateway.services.ServiceType;
import org.apache.knox.gateway.services.security.AliasService;
import org.apache.knox.gateway.services.security.KeystoreService;
import org.apache.knox.gateway.config.GatewayConfig;
import org.apache.knox.gateway.services.GatewayServices;
import org.apache.knox.gateway.services.metrics.MetricsService;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.ProtocolException;
import org.apache.http.auth.AuthSchemeProvider;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.Credentials;
import org.apache.http.client.CookieStore;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.HttpClient;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.RedirectStrategy;
import org.apache.http.client.config.AuthSchemes;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.DefaultConnectionReuseStrategy;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.HttpContext;
import org.apache.http.ssl.SSLContexts;
import org.joda.time.Period;
import org.joda.time.format.PeriodFormatter;
import org.joda.time.format.PeriodFormatterBuilder;

public class DefaultHttpClientFactory implements HttpClientFactory {
  static final String PARAMETER_USE_TWO_WAY_SSL = "useTwoWaySsl";

  @Override
  public HttpClient createHttpClient(FilterConfig filterConfig) {
    HttpClientBuilder builder;
    GatewayConfig gatewayConfig = (GatewayConfig) filterConfig.getServletContext().getAttribute(GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE);
    GatewayServices services = (GatewayServices) filterConfig.getServletContext()
        .getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
    if (gatewayConfig != null && gatewayConfig.isMetricsEnabled()) {
      MetricsService metricsService = services.getService(ServiceType.METRICS_SERVICE);
      builder = metricsService.getInstrumented(HttpClientBuilder.class);
    } else {
      builder = HttpClients.custom();
    }

    // Conditionally set a custom SSLContext
    SSLContext sslContext = createSSLContext(services, filterConfig);
    if(sslContext != null) {
      builder.setSSLSocketFactory(new SSLConnectionSocketFactory(sslContext));
    }

    if (Boolean.parseBoolean(System.getProperty(GatewayConfig.HADOOP_KERBEROS_SECURED))) {
      CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
      credentialsProvider.setCredentials(AuthScope.ANY, new UseJaasCredentials());

      Registry<AuthSchemeProvider> authSchemeRegistry = RegistryBuilder.<AuthSchemeProvider>create()
          .register(AuthSchemes.SPNEGO, new KnoxSpnegoAuthSchemeFactory(true))
          .build();

      builder.setDefaultAuthSchemeRegistry(authSchemeRegistry)
          .setDefaultCookieStore(new HadoopAuthCookieStore(gatewayConfig))
          .setDefaultCredentialsProvider(credentialsProvider);
    } else {
      builder.setDefaultCookieStore(new NoCookieStore());
    }

    builder.setKeepAliveStrategy( DefaultConnectionKeepAliveStrategy.INSTANCE );
    builder.setConnectionReuseStrategy( DefaultConnectionReuseStrategy.INSTANCE );
    builder.setRedirectStrategy( new NeverRedirectStrategy() );
    builder.setRetryHandler( new NeverRetryHandler() );

    int maxConnections = getMaxConnections( filterConfig );
    builder.setMaxConnTotal( maxConnections );
    builder.setMaxConnPerRoute( maxConnections );

    builder.setDefaultRequestConfig( getRequestConfig( filterConfig ) );

    // See KNOX-1530 for details
    builder.disableContentCompression();

    return builder.build();
  }

  /**
   * Conditionally creates a custom {@link SSLContext} based on the Gateway's configuration and whether
   * two-way SSL is enabled or not.
   * <p>
   * If two-way SSL is enabled, then a context with the Gateway's identity and a configured trust store
   * is created.  The trust store is forced to be the same as the identity's keystore if an explicit
   * trust store is not configured.
   * <p>
   * If two-way SSL is not enabled and an explict trust store is configured, then a context with the
   * configured trust store is created.
   * <p>
   * Else, a custom context is not crated and <code>null</code> is returned.
   * <p>
   * This method is package private to allow access to unit tests
   *
   * @param services     the {@link GatewayServices}
   * @param filterConfig a {@link FilterConfig} used to query for parameters for this operation
   * @return a {@link SSLContext} or <code>null</code> if a custom {@link SSLContext} is not needed.
   */
  SSLContext createSSLContext(GatewayServices services, FilterConfig filterConfig) {
    KeyStore identityKeystore;
    char[] identityKeyPassphrase;
    KeyStore trustKeystore;

    KeystoreService ks = services.getService(ServiceType.KEYSTORE_SERVICE);
    try {
      if (Boolean.parseBoolean(filterConfig.getInitParameter(PARAMETER_USE_TWO_WAY_SSL))) {
        AliasService as = services.getService(ServiceType.ALIAS_SERVICE);

        // Get the Gateway's configured identity keystore and key passphrase
        identityKeystore = ks.getKeystoreForGateway();
        identityKeyPassphrase = as.getGatewayIdentityPassphrase();

        // The trustKeystore will be the same as the identityKeystore if a truststore was not explicitly
        // configured in gateway-site (gateway.truststore.password.alias, gateway.truststore.path, gateway.truststore.type)
        // This was the behavior before KNOX-1812
        trustKeystore = ks.getTruststoreForHttpClient();
        if (trustKeystore == null) {
          trustKeystore = identityKeystore;
        }
      } else {
        // If not using twoWaySsl, there is no need to calculate the Gateway's identity keystore or
        // identity key.
        identityKeystore = null;
        identityKeyPassphrase = null;

        // The the behavior before KNOX-1812 was to use the HttpClients default SslContext. However,
        // if a truststore was explicitly configured in gateway-site (gateway.truststore.password.alias,
        // gateway.truststore.path, gateway.truststore.type) create a custom SslContext and use it.
        trustKeystore = ks.getTruststoreForHttpClient();
      }

      // If an identity keystore or a trust store needs to be set, create and return a custom
      // SSLContext; else return null.
      if ((identityKeystore != null) || (trustKeystore != null)) {
        SSLContextBuilder sslContextBuilder = SSLContexts.custom();

        if (identityKeystore != null) {
          sslContextBuilder.loadKeyMaterial(identityKeystore, identityKeyPassphrase);
        }

        if (trustKeystore != null) {
          sslContextBuilder.loadTrustMaterial(trustKeystore, new TrustSelfSignedStrategy());
        }

        return sslContextBuilder.build();
      } else {
        return null;
      }
    } catch (Exception e) {
      throw new IllegalArgumentException("Unable to create SSLContext", e);
    }
  }

  static RequestConfig getRequestConfig( FilterConfig config ) {
    RequestConfig.Builder builder = RequestConfig.custom();
    int connectionTimeout = getConnectionTimeout( config );
    if ( connectionTimeout != -1 ) {
      builder.setConnectTimeout( connectionTimeout );
      builder.setConnectionRequestTimeout( connectionTimeout );
    }
    int socketTimeout = getSocketTimeout( config );
    if( socketTimeout != -1 ) {
      builder.setSocketTimeout( socketTimeout );
    }

    // HttpClient 4.5.7 is broken for %2F handling with url normalization.
    // However, HttpClient 4.5.8+ (HTTPCLIENT-1968) has reasonable url
    // normalization that matches what Knox already does related to url handling.
    //
    // If this view changes later, need to change here as well as make sure
    // rest-assured doesn't use the old HttpClient behavior.
    builder.setNormalizeUri(true);

    return builder.build();
  }

  private static class NoCookieStore implements CookieStore {
    @Override
    public void addCookie(Cookie cookie) {
      //no op
    }

    @Override
    public List<Cookie> getCookies() {
      return Collections.emptyList();
    }

    @Override
    public boolean clearExpired(Date date) {
      return true;
    }

    @Override
    public void clear() {
      //no op
    }
  }

  private static class NeverRedirectStrategy implements RedirectStrategy {
    @Override
    public boolean isRedirected( HttpRequest request, HttpResponse response, HttpContext context )
        throws ProtocolException {
      return false;
    }

    @Override
    public HttpUriRequest getRedirect( HttpRequest request, HttpResponse response, HttpContext context )
        throws ProtocolException {
      return null;
    }
  }

  private static class NeverRetryHandler implements HttpRequestRetryHandler {
    @Override
    public boolean retryRequest( IOException exception, int executionCount, HttpContext context ) {
      return false;
    }
  }

  private static class UseJaasCredentials implements Credentials {

    @Override
    public String getPassword() {
      return null;
    }

    @Override
    public Principal getUserPrincipal() {
      return null;
    }

  }

  private int getMaxConnections( FilterConfig filterConfig ) {
    int maxConnections = 32;
    GatewayConfig config =
        (GatewayConfig)filterConfig.getServletContext().getAttribute( GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE );
    if( config != null ) {
      maxConnections = config.getHttpClientMaxConnections();
    }
    String str = filterConfig.getInitParameter( "httpclient.maxConnections" );
    if( str != null ) {
      try {
        maxConnections = Integer.parseInt( str );
      } catch ( NumberFormatException e ) {
        // Ignore it and use the default.
      }
    }
    return maxConnections;
  }

  private static int getConnectionTimeout( FilterConfig filterConfig ) {
    int timeout = -1;
    GatewayConfig globalConfig =
        (GatewayConfig)filterConfig.getServletContext().getAttribute( GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE );
    if( globalConfig != null ) {
      timeout = globalConfig.getHttpClientConnectionTimeout();
    }
    String str = filterConfig.getInitParameter( "httpclient.connectionTimeout" );
    if( str != null ) {
      try {
        timeout = (int)parseTimeout( str );
      } catch ( Exception e ) {
        // Ignore it and use the default.
      }
    }
    return timeout;
  }

  private static int getSocketTimeout( FilterConfig filterConfig ) {
    int timeout = -1;
    GatewayConfig globalConfig =
        (GatewayConfig)filterConfig.getServletContext().getAttribute( GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE );
    if( globalConfig != null ) {
      timeout = globalConfig.getHttpClientSocketTimeout();
    }
    String str = filterConfig.getInitParameter( "httpclient.socketTimeout" );
    if( str != null ) {
      try {
        timeout = (int)parseTimeout( str );
      } catch ( Exception e ) {
        // Ignore it and use the default.
      }
    }
    return timeout;
  }

  private static long parseTimeout( String s ) {
    PeriodFormatter f = new PeriodFormatterBuilder()
        .appendMinutes().appendSuffix("m"," min")
        .appendSeconds().appendSuffix("s"," sec")
        .appendMillis().toFormatter();
    Period p = Period.parse( s, f );
    return p.toStandardDuration().getMillis();
  }

}
