/*
 * 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.event.BuckEvent;
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.DependencyGraph;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.Maps;
import com.google.common.base.Throwables;

import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.UpgradeRequest;
import org.eclipse.jetty.websocket.api.UpgradeResponse;
import org.eclipse.jetty.websocket.api.WebSocketAdapter;
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;

import java.io.IOException;
import java.util.Collections;
import java.util.Set;

@SuppressWarnings("serial")
public class StreamingWebSocketServlet extends WebSocketServlet {

  private static final JsonNodeFactory jsonNodeFactory = JsonNodeFactory.instance;

  // This is threadsafe
  private final Set<MyWebSocket> connections;

  public StreamingWebSocketServlet() {
    this.connections = Collections.newSetFromMap(Maps.<MyWebSocket, Boolean>newConcurrentMap());
  }

  @Override
  public void configure(WebSocketServletFactory factory) {
    // Most implementations of this method simply invoke factory.register(DispatchSocket.class);
    // however, that requires DispatchSocket to have a no-arg constructor. That does not work for
    // us because we would like all WebSockets created by this factory to have a reference to this
    // parent class. This is why we override the default WebSocketCreator for the factory.
    WebSocketCreator wrapperCreator = new WebSocketCreator() {
      @Override
      public Object createWebSocket(UpgradeRequest req, UpgradeResponse resp) {
        return new MyWebSocket();
      }
    };
    factory.setCreator(wrapperCreator);
  }

  public void tellClients(BuckEvent event) {
    try {
      String message = new ObjectMapper().writeValueAsString(event);
      tellAll(message);
    } catch (IOException e) {
      Throwables.propagate(e);
    }
  }

  /** Sends the message to all WebSockets that are currently connected. */
  private void tellAll(String message) {
    for (MyWebSocket webSocket : connections) {
      if (webSocket.isConnected()) {
        webSocket.getRemote().sendStringByFuture(message);
      }
    }
  }

  /** This is the httpserver component of a WebSocket that maintains a session with one client. */
  public class MyWebSocket extends WebSocketAdapter {

    @Override
    public void onWebSocketConnect(Session session) {
      super.onWebSocketConnect(session);
      connections.add(this);

      // TODO(mbolin): Record all of the events for the last build that was started. For a fresh
      // connection, replay all of the events to get the client caught up. Though must be careful,
      // as this may not be a *new* connection from the client, but a *reconnection*, in which
      // case we have to be careful about redrawing.
    }

    @Override
    public void onWebSocketClose(int statusCode, String reason) {
      super.onWebSocketClose(statusCode, reason);
      connections.remove(this);
    }

    @Override
    public void onWebSocketText(String message) {
      super.onWebSocketText(message);
      if (isNotConnected()) {
        return;
      }

      // TODO(mbolin): Handle requests from client instead of only pushing data down.
    }
  }

  static ObjectNode createJsonForGraph(DependencyGraph graph) {
    ObjectNode nodesToDeps = jsonNodeFactory.objectNode();
    for (BuildRule source : graph.getNodes()) {
      ArrayNode deps = jsonNodeFactory.arrayNode();
      for (BuildRule sink : graph.getOutgoingNodesFor(source)) {
        deps.add(sink.getFullyQualifiedName());
      }
      nodesToDeps.put(source.getFullyQualifiedName(), deps);
    }

    return nodesToDeps;
  }
}
