// 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.sun.net.httpserver.*;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.*;
import java.util.concurrent.Executor;

/**
 * Mock {@link HttpServer}.
 */
public class MockHttpServer extends HttpServer {
  private final InetSocketAddress addr;
  private final List<HttpContext> contexts = new ArrayList<HttpContext>();

  public MockHttpServer() {
    this(new InetSocketAddress(80));
  }

  public MockHttpServer(InetSocketAddress addr) {
    if (addr == null) {
      throw new NullPointerException();
    }
    this.addr = addr;
  }

  private HttpContext instantiateContext(String path) {
    return new MockHttpContext(this, path);
  }

  @Override
  public void bind(InetSocketAddress addr, int backlog) {
    throw new UnsupportedOperationException();
  }

  @Override
  public synchronized HttpContext createContext(String path) {
    HttpContext context = instantiateContext(path);
    for (HttpContext trailContext : contexts) {
      if (path.equals(trailContext.getPath())) {
        throw new IllegalArgumentException("Handler already exists for path");
      }
    }
    contexts.add(context);
    return context;
  }

  @Override
  public synchronized HttpContext createContext(
      String path, HttpHandler handler) {
    HttpContext context = createContext(path);
    context.setHandler(handler);
    return context;
  }

  @Override
  public InetSocketAddress getAddress() {
    return addr;
  }

  @Override
  public Executor getExecutor() {
    throw new UnsupportedOperationException();
  }

  @Override
  public synchronized void removeContext(HttpContext context) {
    if (context == null) {
      throw new NullPointerException();
    }
    contexts.remove(context);
  }

  @Override
  public synchronized void removeContext(String path) {
    if (path == null) {
      throw new NullPointerException();
    }
    Iterator<HttpContext> iter = contexts.iterator();
    while (iter.hasNext()) {
      HttpContext context = iter.next();
      if (context.getPath().equals(path)) {
        iter.remove();
        // Completed.
        return;
      }
    }
    // Not found.
    throw new IllegalArgumentException();
  }

  @Override
  public void setExecutor(Executor executor) {
    throw new UnsupportedOperationException();
  }

  @Override
  public void start() {
    throw new UnsupportedOperationException();
  }

  @Override
  public void stop(int delay) {
    throw new UnsupportedOperationException();
  }

  public synchronized MockHttpExchange createExchange(String method,
      String path) {
    HttpContext best = null;
    int bestLength = -1;
    for (HttpContext context : contexts) {
      if (path.startsWith(context.getPath()) &&
          context.getPath().length() > bestLength) {
        best = context;
        bestLength = context.getPath().length();
      }
    }
    if (best == null) {
      return null;
    }
    return new MockHttpExchange(method, path, best);
  }

  public void handle(HttpExchange ex) throws IOException {
    if (ex == null) {
      throw new NullPointerException();
    }
    HttpContext context = ex.getHttpContext();
    new Filter.Chain(context.getFilters(), context.getHandler()).doFilter(ex);
  }
}
