// 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 com.google.enterprise.adaptor;

import com.google.common.collect.ListMultimap;
import com.google.enterprise.adaptor.secmgr.http.HttpClientInterface;
import com.google.enterprise.adaptor.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 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;
  }

  /** 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);
    }

    /** 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.
        }
      }
    }
  }
}
