/*
 * Copyright 2013-present Facebook, 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.facebook.buck.httpserver;

import com.facebook.buck.io.ProjectFilesystem;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps;

import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.server.handler.ResourceHandler;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;

import java.util.List;
import java.util.Map;

/**
 * A WebSocket server that reports events of buck.
 */
public class WebServer {

  private static final String INDEX_CONTEXT_PATH = "/";
  private static final String STATIC_CONTEXT_PATH = "/static";
  private static final String TRACE_CONTEXT_PATH = "/trace";
  private static final String TRACES_CONTEXT_PATH = "/traces";
  private static final String TRACE_DATA_CONTEXT_PATH = "/tracedata";

  private Optional<Integer> port;
  private final ProjectFilesystem projectFilesystem;
  private final String staticContentDirectory;
  private final Server server;
  private final StreamingWebSocketServlet streamingWebSocketServlet;

  /**
   * @param port If 0, then an <a href="http://en.wikipedia.org/wiki/Ephemeral_port">
   *     ephemeral port</a> will be assigned. Use {@link #getPort()} to find out which port is being
   *     used.
   */
  public WebServer(
      int port,
      ProjectFilesystem projectFilesystem,
      String staticContentDirectory) {
    this.projectFilesystem = projectFilesystem;
    this.staticContentDirectory = staticContentDirectory;
    this.port = Optional.absent();
    this.server = new Server(port);
    this.streamingWebSocketServlet = new StreamingWebSocketServlet();
  }

  public Optional<Integer> getPort() {
    if (!port.isPresent()) {
      for (Connector connector : server.getConnectors()) {
        if (connector instanceof ServerConnector) {
          port = Optional.of(((ServerConnector) connector).getLocalPort());
          break;
        }
      }
    }

    return port;
  }

  public WebServerBuckEventListener createListener() {
    return new WebServerBuckEventListener(this);
  }

  public StreamingWebSocketServlet getStreamingWebSocketServlet() {
    return streamingWebSocketServlet;
  }

  public synchronized void start() throws WebServerException {
    if (server.isStarted()) {
      return;
    }

    // Package up all of the handlers into a ContextHandlerCollection to serve as the handler for
    // the server.
    List<? extends Handler> handlers = createHandlers();
    ContextHandlerCollection contexts = new ContextHandlerCollection();
    contexts.setHandlers(handlers.toArray(new Handler[0]));
    server.setHandler(contexts);

    try {
      server.start();
    } catch (Exception e) {
      throw new WebServerException("Cannot start Websocket server.", e);
    }
  }

  @VisibleForTesting
  List<ContextHandler> createHandlers() {
    Map<String, Handler> contextPathToHandler = Maps.newHashMap();

    contextPathToHandler.put(INDEX_CONTEXT_PATH, new TemplateHandler(new IndexHandlerDelegate()));

    ResourceHandler resourceHandler = new ResourceHandler();
    resourceHandler.setResourceBase(staticContentDirectory);
    contextPathToHandler.put(STATIC_CONTEXT_PATH, resourceHandler);

    // Handlers for traces.
    TracesHelper tracesHelper = new TracesHelper(projectFilesystem);
    contextPathToHandler.put(TRACE_CONTEXT_PATH, new TemplateHandler(
        new TraceHandlerDelegate(tracesHelper)));
    contextPathToHandler.put(TRACES_CONTEXT_PATH, new TemplateHandler(
        new TracesHandlerDelegate(tracesHelper)));
    contextPathToHandler.put(TRACE_DATA_CONTEXT_PATH, new TraceDataHandler(tracesHelper));

    ImmutableList.Builder<ContextHandler> handlers = ImmutableList.builder();
    for (Map.Entry<String, Handler> entry : contextPathToHandler.entrySet()) {
      String contextPath = entry.getKey();
      Handler handler = entry.getValue();
      ContextHandler contextHandler = new ContextHandler(contextPath);
      contextHandler.setHandler(handler);
      handlers.add(contextHandler);
    }

    // Create a handler that acts as a WebSocket server.
    ServletContextHandler servletContextHandler = new ServletContextHandler(
        /* parent */ server,
        /* contextPath */ "/comet",
        /* sessions */ true,
        /* security */ false);
    servletContextHandler.addServlet(new ServletHolder(streamingWebSocketServlet), "/echo");
    handlers.add(servletContextHandler);
    return handlers.build();
  }

  public synchronized void stop() throws WebServerException {
    if (!server.isRunning()) {
      return;
    }
    try {
      server.stop();
    } catch (Exception e) {
      throw new WebServerException("Cannot stop Websocket server.", e);
    }
  }

  @SuppressWarnings("serial")
  public static class WebServerException extends Exception {

    public WebServerException(String message, Exception clause) {
      super(message, clause);
    }
  }
}
