/*
 * Copyright (C) 2012 Square, Inc.
 *
 * 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 com.squareup.okhttp.internal.http;

import com.squareup.okhttp.Address;
import com.squareup.okhttp.ConnectionSpec;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Route;
import com.squareup.okhttp.internal.Internal;
import com.squareup.okhttp.internal.Network;
import com.squareup.okhttp.internal.RouteDatabase;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.URI;
import java.net.UnknownServiceException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.NoSuchElementException;
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.SSLProtocolException;

import static com.squareup.okhttp.internal.Util.getEffectivePort;

/**
 * Selects routes to connect to an origin server. Each connection requires a
 * choice of proxy server, IP address, and TLS mode. Connections may also be
 * recycled.
 */
public final class RouteSelector {
  private final Address address;
  private final URI uri;
  private final Network network;
  private final OkHttpClient client;
  private final RouteDatabase routeDatabase;
  private final Request request;

  /* The most recently attempted route. */
  private Proxy lastProxy;
  private InetSocketAddress lastInetSocketAddress;
  private ConnectionSpec lastSpec;

  /* State for negotiating the next proxy to use. */
  private List<Proxy> proxies = Collections.emptyList();
  private int nextProxyIndex;

  /* State for negotiating the next socket address to use. */
  private List<InetSocketAddress> inetSocketAddresses = Collections.emptyList();
  private int nextInetSocketAddressIndex;

  /* Specs to attempt with the connection. */
  private List<ConnectionSpec> connectionSpecs = Collections.emptyList();
  private int nextSpecIndex;

  /* State for negotiating failed routes */
  private final List<Route> postponedRoutes = new ArrayList<>();

  private RouteSelector(Address address, URI uri, OkHttpClient client, Request request) {
    this.address = address;
    this.uri = uri;
    this.client = client;
    this.routeDatabase = Internal.instance.routeDatabase(client);
    this.network = Internal.instance.network(client);
    this.request = request;

    resetNextProxy(uri, address.getProxy());
  }

  public static RouteSelector get(Address address, Request request, OkHttpClient client)
      throws IOException {
    return new RouteSelector(address, request.uri(), client, request);
  }

  /**
   * Returns true if there's another route to attempt. Every address has at
   * least one route.
   */
  public boolean hasNext() {
    return hasNextConnectionSpec()
        || hasNextInetSocketAddress()
        || hasNextProxy()
        || hasNextPostponed();
  }

  public Route next() throws IOException {
    // Compute the next route to attempt.
    if (!hasNextConnectionSpec()) {
      if (!hasNextInetSocketAddress()) {
        if (!hasNextProxy()) {
          if (!hasNextPostponed()) {
            throw new NoSuchElementException();
          }
          return nextPostponed();
        }
        lastProxy = nextProxy();
      }
      lastInetSocketAddress = nextInetSocketAddress();
    }
    lastSpec = nextConnectionSpec();

    final boolean shouldSendTlsFallbackIndicator = shouldSendTlsFallbackIndicator(lastSpec);
    Route route = new Route(address, lastProxy, lastInetSocketAddress, lastSpec,
        shouldSendTlsFallbackIndicator);
    if (routeDatabase.shouldPostpone(route)) {
      postponedRoutes.add(route);
      // We will only recurse in order to skip previously failed routes. They will be tried last.
      return next();
    }

    return route;
  }

  private boolean shouldSendTlsFallbackIndicator(ConnectionSpec connectionSpec) {
    return connectionSpec != connectionSpecs.get(0)
        && connectionSpec.isTls();
  }

  /**
   * Clients should invoke this method when they encounter a connectivity
   * failure on a connection returned by this route selector.
   */
  public void connectFailed(Route failedRoute, IOException failure) {
    if (failedRoute.getProxy().type() != Proxy.Type.DIRECT && address.getProxySelector() != null) {
      // Tell the proxy selector when we fail to connect on a fresh connection.
      address.getProxySelector().connectFailed(uri, failedRoute.getProxy().address(), failure);
    }

    routeDatabase.failed(failedRoute);

    // If the previously returned route's problem was not related to the connection's spec, and the
    // next route only changes that, we shouldn't even attempt it. This suppresses it in both this
    // selector and also in the route database.
    if (!(failure instanceof SSLHandshakeException) && !(failure instanceof SSLProtocolException)) {
      while (nextSpecIndex < connectionSpecs.size()) {
        ConnectionSpec connectionSpec = connectionSpecs.get(nextSpecIndex++);
        final boolean shouldSendTlsFallbackIndicator =
            shouldSendTlsFallbackIndicator(connectionSpec);
        Route toSuppress = new Route(address, lastProxy, lastInetSocketAddress, connectionSpec,
            shouldSendTlsFallbackIndicator);
        routeDatabase.failed(toSuppress);
      }
    }
  }

  /** Prepares the proxy servers to try. */
  private void resetNextProxy(URI uri, Proxy proxy) {
    if (proxy != null) {
      // If the user specifies a proxy, try that and only that.
      proxies = Collections.singletonList(proxy);
    } else {
      // Try each of the ProxySelector choices until one connection succeeds. If none succeed
      // then we'll try a direct connection below.
      proxies = new ArrayList<>();
      List<Proxy> selectedProxies = client.getProxySelector().select(uri);
      if (selectedProxies != null) proxies.addAll(selectedProxies);
      // Finally try a direct connection. We only try it once!
      proxies.removeAll(Collections.singleton(Proxy.NO_PROXY));
      proxies.add(Proxy.NO_PROXY);
    }
    nextProxyIndex = 0;
  }

  /** Returns true if there's another proxy to try. */
  private boolean hasNextProxy() {
    return nextProxyIndex < proxies.size();
  }

  /** Returns the next proxy to try. May be PROXY.NO_PROXY but never null. */
  private Proxy nextProxy() throws IOException {
    if (!hasNextProxy()) {
      throw new SocketException("No route to " + address.getUriHost()
          + "; exhausted proxy configurations: " + proxies);
    }
    Proxy result = proxies.get(nextProxyIndex++);
    resetNextInetSocketAddress(result);
    return result;
  }

  /** Prepares the socket addresses to attempt for the current proxy or host. */
  private void resetNextInetSocketAddress(Proxy proxy) throws IOException {
    // Clear the addresses. Necessary if getAllByName() below throws!
    inetSocketAddresses = new ArrayList<>();

    String socketHost;
    int socketPort;
    if (proxy.type() == Proxy.Type.DIRECT || proxy.type() == Proxy.Type.SOCKS) {
      socketHost = address.getUriHost();
      socketPort = getEffectivePort(uri);
    } else {
      SocketAddress proxyAddress = proxy.address();
      if (!(proxyAddress instanceof InetSocketAddress)) {
        throw new IllegalArgumentException(
            "Proxy.address() is not an " + "InetSocketAddress: " + proxyAddress.getClass());
      }
      InetSocketAddress proxySocketAddress = (InetSocketAddress) proxyAddress;
      socketHost = getHostString(proxySocketAddress);
      socketPort = proxySocketAddress.getPort();
    }

    if (socketPort < 1 || socketPort > 65535) {
      throw new SocketException("No route to " + socketHost + ":" + socketPort
          + "; port is out of range");
    }

    // Try each address for best behavior in mixed IPv4/IPv6 environments.
    for (InetAddress inetAddress : network.resolveInetAddresses(socketHost)) {
      inetSocketAddresses.add(new InetSocketAddress(inetAddress, socketPort));
    }
    nextInetSocketAddressIndex = 0;
  }

  /**
   * Obtain a "host" from an {@link InetSocketAddress}. This returns a string containing either an
   * actual host name or a numeric IP address.
   */
  // Visible for testing
  static String getHostString(InetSocketAddress socketAddress) {
    InetAddress address = socketAddress.getAddress();
    if (address == null) {
      // The InetSocketAddress was specified with a string (either a numeric IP or a host name). If
      // it is a name, all IPs for that name should be tried. If it is an IP address, only that IP
      // address should be tried.
      return socketAddress.getHostName();
    }
    // The InetSocketAddress has a specific address: we should only try that address. Therefore we
    // return the address and ignore any host name that may be available.
    return address.getHostAddress();
  }

  /** Returns true if there's another socket address to try. */
  private boolean hasNextInetSocketAddress() {
    return nextInetSocketAddressIndex < inetSocketAddresses.size();
  }

  /** Returns the next socket address to try. */
  private InetSocketAddress nextInetSocketAddress() throws IOException {
    if (!hasNextInetSocketAddress()) {
      throw new SocketException("No route to " + address.getUriHost()
          + "; exhausted inet socket addresses: " + inetSocketAddresses);
    }
    InetSocketAddress result = inetSocketAddresses.get(nextInetSocketAddressIndex++);
    resetConnectionSpecs();
    return result;
  }

  /** Prepares the connection specs to attempt. */
  private void resetConnectionSpecs() {
    connectionSpecs = new ArrayList<>();
    List<ConnectionSpec> specs = address.getConnectionSpecs();
    for (int i = 0, size = specs.size(); i < size; i++) {
      ConnectionSpec spec = specs.get(i);
      if (request.isHttps() == spec.isTls()) {
        connectionSpecs.add(spec);
      }
    }
    nextSpecIndex = 0;
  }

  /** Returns true if there's another connection spec to try. */
  private boolean hasNextConnectionSpec() {
    return nextSpecIndex < connectionSpecs.size();
  }

  /** Returns the next connection spec to try. */
  private ConnectionSpec nextConnectionSpec() throws IOException {
    if (connectionSpecs.isEmpty()) {
      throw new UnknownServiceException("No route to "
          + ((uri.getScheme() != null) ? (uri.getScheme() + "://") : "//") + address.getUriHost()
          + "; no connection specs");
    }
    if (!hasNextConnectionSpec()) {
      throw new SocketException("No route to "
          + ((uri.getScheme() != null) ? (uri.getScheme() + "://") : "//") + address.getUriHost()
          + "; exhausted connection specs: " + connectionSpecs);
    }
    return connectionSpecs.get(nextSpecIndex++);
  }

  /** Returns true if there is another postponed route to try. */
  private boolean hasNextPostponed() {
    return !postponedRoutes.isEmpty();
  }

  /** Returns the next postponed route to try. */
  private Route nextPostponed() {
    return postponedRoutes.remove(0);
  }
}
