// Copyright 2011 Google Inc. All Rights Reserved.
//
// 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 adaptorlib;

import com.google.common.collect.ListMultimap;
import com.google.enterprise.secmgr.common.CookieStore;
import com.google.enterprise.secmgr.common.GCookie;
import com.google.enterprise.secmgr.http.HttpClientInterface;
import com.google.enterprise.secmgr.http.HttpExchange;

import com.sun.net.httpserver.Headers;

import java.io.*;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.*;

/**
 * Mock {@link HttpClientInterface}.
 */
public abstract class MockHttpClient implements HttpClientInterface {
  private static final String POST_ENCODING = "UTF-8";

  protected abstract void handleExchange(ClientExchange ex);

  @Override
  public HttpExchange headExchange(URL url) {
    throw new UnsupportedOperationException();
  }

  @Override
  public HttpExchange getExchange(URL url) {
    throw new UnsupportedOperationException();
  }

  @Override
  public HttpExchange postExchange(URL url,
                                   ListMultimap<String, String> parameters) {
    HttpExchange exchange = new ClientExchange(url, "POST");
    if (parameters != null) {
      exchange.setRequestHeader("Content-Type",
          "application/x-www-form-urlencoded; charset=" + POST_ENCODING);
      for (String name : parameters.keySet()) {
        for (String value : parameters.get(name)) {
          exchange.addParameter(name, value);
        }
      }
    }
    return exchange;
  }

  @Override
  public HttpExchange newHttpExchange(URL url) {
    throw new UnsupportedOperationException();
  }

  @Override
  public Connection getConnection(URL url) throws IOException {
    throw new UnsupportedOperationException();
  }

  @Override
  public HttpExchange headExchange(Connection connection, URL url) {
    throw new UnsupportedOperationException();
  }

  @Override
  public HttpExchange getExchange(Connection connection, URL url) {
    throw new UnsupportedOperationException();
  }

  @Override
  public HttpExchange postExchange(Connection connection, URL url,
                                   ListMultimap<String, String> parameters) {
    throw new UnsupportedOperationException();
  }

  @Override
  public HttpExchange newHttpExchange(Connection connection, URL url) {
    throw new UnsupportedOperationException();
  }

  @Override
  public void setRequestTimeoutMillis(int millisec) {
    throw new UnsupportedOperationException();
  }

  /** Mocked exchange that calls {@link #handleExchange}. */
  protected class ClientExchange implements HttpExchange {
    private final URL url;
    private final String method;
    private byte[] requestBody;
    /** POST parameters */
    // Alternates between key and value
    private List<String> parameters = new ArrayList<String>();
    private boolean connected = false;
    private Headers requestHeaders = new Headers();
    private int responseCode = -1;
    private Headers responseHeaders = new Headers();
    private InputStream responseStream;

    public ClientExchange(URL url, String method) {
      this.url = url;
      this.method = method;
    }

    @Override
    public void setProxy(String proxy) {
      throw new UnsupportedOperationException();
    }

    @Override
    public void setBasicAuthCredentials(String username, String password) {
      throw new UnsupportedOperationException();
    }

    @Override
    public void setFollowRedirects(boolean followRedirects) {
    }

    @Override
    public void setTimeout(int timeout) {
    }

    @Override
    public String getHttpMethod() {
      return method;
    }

    @Override
    public URL getUrl() {
      return url;
    }

    @Override
    public void addParameter(String name, String value) {
      if (!"POST".equals(method)) {
        throw new IllegalStateException();
      }
      parameters.add(name);
      parameters.add(value);
    }

    @Override
    public void addRequestHeader(String name, String value) {
      requestHeaders.add(name, value);
    }

    @Override
    public void setRequestHeader(String name, String value) {
      requestHeaders.set(name, value);
    }

    @Override
    public List<String> getRequestHeaderValues(String headerName) {
      return requestHeaders.get(headerName);
    }

    @Override
    public String getRequestHeaderValue(String headerName) {
      return requestHeaders.getFirst(headerName);
    }

    @Override
    public void addCookies(Iterable<GCookie> cookies) {
      throw new UnsupportedOperationException();
    }

    @Override
    public CookieStore getCookies() {
      throw new UnsupportedOperationException();
    }

    /** Does not copy provided byte array. */
    @Override
    public void setRequestBody(byte[] byteArrayRequestEntity) {
      requestBody = byteArrayRequestEntity;
    }

    public byte[] getRequestBody() {
      return requestBody;
    }

    @Override
    public int exchange() throws IOException {
      if (parameters.size() > 0) {
        if (requestBody != null) {
          // Thus, having parameters is equivalent to having a requestBody, and
          // we can't have both.
          throw new IllegalStateException();
        }
      }
      handleExchange(this);
      if (responseCode == -1) {
        throw new IllegalStateException("handleExchange must set statusCode");
      }
      connected = true;
      return getStatusCode();
    }

    @Override
    public String getResponseEntityAsString() throws IOException {
      Charset charset = Charset.forName("UTF-8");
      if (charset == null) {
        throw new RuntimeException("Unknown charset: " + charset);
      }
      InputStream is = getResponseEntityAsStream();
      StringBuilder sb = new StringBuilder();
      try {
        Reader reader = new InputStreamReader(is, charset);
        char[] buf = new char[1024];
        int read;
        while ((read = reader.read(buf)) != -1) {
          sb.append(buf, 0, read);
        }
      } finally {
        is.close();
      }
      return sb.toString();
    }

    @Override
    public InputStream getResponseEntityAsStream() throws IOException {
      return responseStream;
    }

    public void setResponseStream(InputStream responseStream) {
      this.responseStream = responseStream;
    }

    public void setResponseStream(byte[] bytes) {
      this.responseStream = new ByteArrayInputStream(bytes);
    }

    @Override
    public List<String> getResponseHeaderValues(String headerName) {
      return responseHeaders.get(headerName);
    }

    @Override
    public String getResponseHeaderValue(String headerName) {
      return responseHeaders.getFirst(headerName);
    }

    @Override
    public ListMultimap<String, String> getResponseHeaders() {
      throw new UnsupportedOperationException();
    }

    @Override
    public int getStatusCode() {
      return responseCode;
    }

    public void setStatusCode(int responseCode) {
      this.responseCode = responseCode;
    }

    @Override
    public void close() {
      if (connected) {
        try {
          responseStream.close();
        } catch (IOException ex) {
          // Ignore.
        }
      }
    }
  }
}
