/*
 * Copyright (c) 2015, the Dart project authors.
 *
 * Licensed under the Eclipse Public License v1.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.eclipse.org/legal/epl-v10.html
 *
 * 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 org.dartlang.vm.service;

import com.google.common.collect.Maps;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import de.roderick.weberknecht.WebSocket;
import de.roderick.weberknecht.WebSocketEventHandler;
import de.roderick.weberknecht.WebSocketException;
import de.roderick.weberknecht.WebSocketMessage;
import org.dartlang.vm.service.consumer.*;
import org.dartlang.vm.service.element.*;
import org.dartlang.vm.service.internal.RequestSink;
import org.dartlang.vm.service.internal.VmServiceConst;
import org.dartlang.vm.service.internal.WebSocketRequestSink;
import org.dartlang.vm.service.logging.Logging;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Internal {@link VmService} base class containing non-generated code.
 */
@SuppressWarnings({"unused", "WeakerAccess"})
abstract class VmServiceBase implements VmServiceConst {
  /**
   * Connect to the VM observatory service via the specified URI
   *
   * @return an API object for interacting with the VM service (not {@code null}).
   */
  public static VmService connect(final String url) throws IOException {
    // Validate URL
    URI uri;
    try {
      uri = new URI(url);
    } catch (URISyntaxException e) {
      throw new IOException("Invalid URL: " + url, e);
    }
    String wsScheme = uri.getScheme();
    if (!"ws".equals(wsScheme) && !"wss".equals(wsScheme)) {
      throw new IOException("Unsupported URL scheme: " + wsScheme);
    }

    // Create web socket and observatory
    WebSocket webSocket;
    try {
      webSocket = new WebSocket(uri);
    } catch (WebSocketException e) {
      throw new IOException("Failed to create websocket: " + url, e);
    }
    final VmService vmService = new VmService();

    // Setup event handler for forwarding responses
    webSocket.setEventHandler(new WebSocketEventHandler() {
      @Override
      public void onClose() {
        Logging.getLogger().logInformation("VM connection closed: " + url);

        vmService.connectionClosed();
      }

      @Override
      public void onMessage(WebSocketMessage message) {
        Logging.getLogger().logInformation("VM message: " + message.getText());
        try {
          vmService.processMessage(message.getText());
        } catch (Exception e) {
          Logging.getLogger().logError(e.getMessage(), e);
        }
      }

      @Override
      public void onOpen() {
        vmService.connectionOpened();

        Logging.getLogger().logInformation("VM connection open: " + url);
      }

      @Override
      public void onPing() {
      }

      @Override
      public void onPong() {
      }
    });

    // Establish WebSocket Connection
    //noinspection TryWithIdenticalCatches
    try {
      webSocket.connect();
    } catch (WebSocketException e) {
      throw new IOException("Failed to connect: " + url, e);
    } catch (ArrayIndexOutOfBoundsException e) {
      // The weberknecht can occasionally throw an array index exception if a connect terminates on initial connect
      // (de.roderick.weberknecht.WebSocket.connect, WebSocket.java:126).
      throw new IOException("Failed to connect: " + url, e);
    }
    vmService.requestSink = new WebSocketRequestSink(webSocket);

    // Check protocol version
    final CountDownLatch latch = new CountDownLatch(1);
    final String[] errMsg = new String[1];
    vmService.getVersion(new VersionConsumer() {
      @Override
      public void onError(RPCError error) {
        String msg = "Failed to determine protocol version: " + error.getCode() + "\n  message: "
            + error.getMessage() + "\n  details: " + error.getDetails();
        Logging.getLogger().logInformation(msg);
        errMsg[0] = msg;
      }

      @Override
      public void received(Version version) {
        vmService.runtimeVersion = version;

        latch.countDown();
      }
    });

    try {
      if (!latch.await(5, TimeUnit.SECONDS)) {
        throw new IOException("Failed to determine protocol version");
      }
      if (errMsg[0] != null) {
        throw new IOException(errMsg[0]);
      }
    } catch (InterruptedException e) {
      throw new RuntimeException("Interrupted while waiting for response", e);
    }

    return vmService;
  }

  /**
   * Connect to the VM observatory service on the given local port.
   *
   * @return an API object for interacting with the VM service (not {@code null}).
   *
   * @deprecated prefer the Url based constructor {@link VmServiceBase#connect}
   */
  @Deprecated
  public static VmService localConnect(int port) throws IOException {
    return connect("ws://localhost:" + port + "/ws");
  }

  /**
   * A mapping between {@link String} ids' and the associated {@link Consumer} that was passed when
   * the request was made. Synchronize against {@link #consumerMapLock} before accessing this field.
   */
  private final Map<String, Consumer> consumerMap = Maps.newHashMap();

  /**
   * The object used to synchronize access to {@link #consumerMap}.
   */
  private final Object consumerMapLock = new Object();

  /**
   * The unique ID for the next request.
   */
  private final AtomicInteger nextId = new AtomicInteger();

  /**
   * A list of objects to which {@link Event}s from the VM are forwarded.
   */
  private final List<VmServiceListener> vmListeners = new ArrayList<>();

  /**
   * A list of objects to which {@link Event}s from the VM are forwarded.
   */
  private final Map<String, RemoteServiceRunner> remoteServiceRunners = Maps.newHashMap();

  /**
   * The channel through which observatory requests are made.
   */
  RequestSink requestSink;

  Version runtimeVersion;

  /**
   * Add a listener to receive {@link Event}s from the VM.
   */
  public void addVmServiceListener(VmServiceListener listener) {
    vmListeners.add(listener);
  }

  /**
   * Remove the given listener from the VM.
   */
  public void removeVmServiceListener(VmServiceListener listener) {
    vmListeners.remove(listener);
  }

  /**
   * Add a VM RemoteServiceRunner.
   */
  public void addServiceRunner(String service, RemoteServiceRunner runner) {
    remoteServiceRunners.put(service, runner);
  }

  /**
   * Remove a VM RemoteServiceRunner.
   */
  public void removeServiceRunner(String service) {
    remoteServiceRunners.remove(service);
  }

  /**
   * Return the VM service protocol version supported by the current debug connection.
   */
  public Version getRuntimeVersion() {
    return runtimeVersion;
  }

  /**
   * Disconnect from the VM observatory service.
   */
  public void disconnect() {
    requestSink.close();
  }

  /**
   * Return the instance with the given identifier.
   */
  public void getInstance(String isolateId, String instanceId, final GetInstanceConsumer consumer) {
    getObject(isolateId, instanceId, new GetObjectConsumer() {

      @Override
      public void onError(RPCError error) {
        consumer.onError(error);
      }

      @Override
      public void received(Obj response) {
        if (response instanceof Instance) {
          consumer.received((Instance) response);
        } else {
          onError(RPCError.unexpected("Instance", response));
        }
      }

      @Override
      public void received(Sentinel response) {
        onError(RPCError.unexpected("Instance", response));
      }
    });
  }

  /**
   * Return the library with the given identifier.
   */
  public void getLibrary(String isolateId, String libraryId, final GetLibraryConsumer consumer) {
    getObject(isolateId, libraryId, new GetObjectConsumer() {

      @Override
      public void onError(RPCError error) {
        consumer.onError(error);
      }

      @Override
      public void received(Obj response) {
        if (response instanceof Library) {
          consumer.received((Library) response);
        } else {
          onError(RPCError.unexpected("Library", response));
        }
      }

      @Override
      public void received(Sentinel response) {
        onError(RPCError.unexpected("Library", response));
      }
    });
  }

  public abstract void getObject(String isolateId, String objectId, GetObjectConsumer consumer);

  /**
   * Invoke a specific service protocol extension method.
   * <p>
   * See https://api.dart.dev/stable/dart-developer/dart-developer-library.html.
   */
  public void callServiceExtension(String isolateId, String method, ServiceExtensionConsumer consumer) {
    JsonObject params = new JsonObject();
    params.addProperty("isolateId", isolateId);
    request(method, params, consumer);
  }

  /**
   * Invoke a specific service protocol extension method.
   * <p>
   * See https://api.dart.dev/stable/dart-developer/dart-developer-library.html.
   */
  public void callServiceExtension(String isolateId, String method, JsonObject params, ServiceExtensionConsumer consumer) {
    params.addProperty("isolateId", isolateId);
    request(method, params, consumer);
  }

  /**
   * Sends the request and associates the request with the passed {@link Consumer}.
   */
  protected void request(String method, JsonObject params, Consumer consumer) {

    // Assemble the request
    String id = Integer.toString(nextId.incrementAndGet());
    JsonObject request = new JsonObject();

    request.addProperty(JSONRPC, JSONRPC_VERSION);
    request.addProperty(ID, id);
    request.addProperty(METHOD, method);
    request.add(PARAMS, params);

    // Cache the consumer to receive the response
    synchronized (consumerMapLock) {
      consumerMap.put(id, consumer);
    }

    // Send the request
    requestSink.add(request);
  }

  public void connectionOpened() {
    for (VmServiceListener listener : new ArrayList<>(vmListeners)) {
      try {
        listener.connectionOpened();
      } catch (Exception e) {
        Logging.getLogger().logError("Exception notifying listener", e);
      }
    }
  }

  private void forwardEvent(String streamId, Event event) {
    for (VmServiceListener listener : new ArrayList<>(vmListeners)) {
      try {
        listener.received(streamId, event);
      } catch (Exception e) {
        Logging.getLogger().logError("Exception processing event: " + streamId + ", " + event.getJson(), e);
      }
    }
  }

  public void connectionClosed() {
    for (VmServiceListener listener : new ArrayList<>(vmListeners)) {
      try {
        listener.connectionClosed();
      } catch (Exception e) {
        Logging.getLogger().logError("Exception notifying listener", e);
      }
    }
  }

  abstract void forwardResponse(Consumer consumer, String type, JsonObject json);

  void logUnknownResponse(Consumer consumer, JsonObject json) {
    Class<? extends Consumer> consumerClass = consumer.getClass();
    StringBuilder msg = new StringBuilder();
    msg.append("Expected response for ").append(consumerClass).append("\n");
    for (Class<?> interf : consumerClass.getInterfaces()) {
      msg.append("  implementing ").append(interf).append("\n");
    }
    msg.append("  but received ").append(json);
    Logging.getLogger().logError(msg.toString());
  }

  /**
   * Process the response from the VM service and forward that response to the consumer associated
   * with the response id.
   */
  void processMessage(String jsonText) {
    if (jsonText == null || jsonText.isEmpty()) {
      return;
    }

    // Decode the JSON
    JsonObject json;
    try {
      json = (JsonObject) new JsonParser().parse(jsonText);
    } catch (Exception e) {
      Logging.getLogger().logError("Parse message failed: " + jsonText, e);
      return;
    }

    if (json.has("method")) {
      if (!json.has(PARAMS)) {
        final String message = "Missing " + PARAMS;
        Logging.getLogger().logError(message);
        final JsonObject response = new JsonObject();
        response.addProperty(JSONRPC, JSONRPC_VERSION);
        final JsonObject error = new JsonObject();
        error.addProperty(CODE, INVALID_REQUEST);
        error.addProperty(MESSAGE, message);
        response.add(ERROR, error);
        requestSink.add(response);
        return;
      }
      if (json.has("id")) {
        processRequest(json);
      } else {
        processNotification(json);
      }
    } else if (json.has("result") || json.has("error")) {
      processResponse(json);
    } else {
      Logging.getLogger().logError("Malformed message");
    }
  }

  void processRequest(JsonObject json) {
    final JsonObject response = new JsonObject();
    response.addProperty(JSONRPC, JSONRPC_VERSION);

    // Get the consumer associated with this request
    String id;
    try {
      id = json.get(ID).getAsString();
    } catch (Exception e) {
      final String message = "Request malformed " + ID;
      Logging.getLogger().logError(message, e);
      final JsonObject error = new JsonObject();
      error.addProperty(CODE, INVALID_REQUEST);
      error.addProperty(MESSAGE, message);
      response.add(ERROR, error);
      requestSink.add(response);
      return;
    }

    response.addProperty(ID, id);

    String method;
    try {
      method = json.get(METHOD).getAsString();
    } catch (Exception e) {
      final String message = "Request malformed " + METHOD;
      Logging.getLogger().logError(message, e);
      final JsonObject error = new JsonObject();
      error.addProperty(CODE, INVALID_REQUEST);
      error.addProperty(MESSAGE, message);
      response.add(ERROR, error);
      requestSink.add(response);
      return;
    }

    JsonObject params;
    try {
      params = json.get(PARAMS).getAsJsonObject();
    } catch (Exception e) {
      final String message = "Request malformed " + METHOD;
      Logging.getLogger().logError(message, e);
      final JsonObject error = new JsonObject();
      error.addProperty(CODE, INVALID_REQUEST);
      error.addProperty(MESSAGE, message);
      response.add(ERROR, error);
      requestSink.add(response);
      return;
    }

    if (!remoteServiceRunners.containsKey(method)) {
      final String message = "Unknown service " + method;
      Logging.getLogger().logError(message);
      final JsonObject error = new JsonObject();
      error.addProperty(CODE, METHOD_NOT_FOUND);
      error.addProperty(MESSAGE, message);
      response.add(ERROR, error);
      requestSink.add(response);
      return;
    }

    final RemoteServiceRunner runner = remoteServiceRunners.get(method);
    try {
      runner.run(params, new RemoteServiceCompleter() {
        public void result(JsonObject result) {
          response.add(RESULT, result);
          requestSink.add(response);
        }

        public void error(int code, String message, JsonObject data) {
          final JsonObject error = new JsonObject();
          error.addProperty(CODE, code);
          error.addProperty(MESSAGE, message);
          if (data != null) {
            error.add(DATA, data);
          }
          response.add(ERROR, error);
          requestSink.add(response);
        }
      });
    } catch (Exception e) {
      final String message = "Internal Server Error";
      Logging.getLogger().logError(message, e);
      final JsonObject error = new JsonObject();
      error.addProperty(CODE, SERVER_ERROR);
      error.addProperty(MESSAGE, message);
      response.add(ERROR, error);
      requestSink.add(response);
    }
  }

  private static final RemoteServiceCompleter ignoreCallback =
      new RemoteServiceCompleter() {
        public void result(JsonObject result) {
          // ignore
        }

        public void error(int code, String message, JsonObject data) {
          // ignore
        }
      };

  void processNotification(JsonObject json) {
    String method;
    try {
      method = json.get(METHOD).getAsString();
    } catch (Exception e) {
      Logging.getLogger().logError("Request malformed " + METHOD, e);
      return;
    }
    JsonObject params;
    try {
      params = json.get(PARAMS).getAsJsonObject();
    } catch (Exception e) {
      Logging.getLogger().logError("Event missing " + PARAMS, e);
      return;
    }
    if ("streamNotify".equals(method)) {
      String streamId;
      try {
        streamId = params.get(STREAM_ID).getAsString();
      } catch (Exception e) {
        Logging.getLogger().logError("Event missing " + STREAM_ID, e);
        return;
      }
      Event event;
      try {
        event = new Event(params.get(EVENT).getAsJsonObject());
      } catch (Exception e) {
        Logging.getLogger().logError("Event missing " + EVENT, e);
        return;
      }
      forwardEvent(streamId, event);
    } else {
      if (!remoteServiceRunners.containsKey(method)) {
        Logging.getLogger().logError("Unknown service " + method);
        return;
      }

      final RemoteServiceRunner runner = remoteServiceRunners.get(method);
      try {
        runner.run(params, ignoreCallback);
      } catch (Exception e) {
        Logging.getLogger().logError("Internal Server Error", e);
      }
    }
  }

  void processResponse(JsonObject json) {
    JsonElement idElem = json.get(ID);
    if (idElem == null) {
      Logging.getLogger().logError("Response missing " + ID);
      return;
    }

    // Get the consumer associated with this response
    String id;
    try {
      id = idElem.getAsString();
    } catch (Exception e) {
      Logging.getLogger().logError("Response missing " + ID, e);
      return;
    }
    Consumer consumer = consumerMap.remove(id);
    if (consumer == null) {
      Logging.getLogger().logError("No consumer associated with " + ID + ": " + id);
      return;
    }

    // Forward the response if the request was successfully executed
    JsonElement resultElem = json.get(RESULT);
    if (resultElem != null) {
      JsonObject result;
      try {
        result = resultElem.getAsJsonObject();
      } catch (Exception e) {
        Logging.getLogger().logError("Response has invalid " + RESULT, e);
        return;
      }
      String responseType = "";
      if (result.has(TYPE)) {
        responseType = result.get(TYPE).getAsString();
      }
      // ServiceExtensionConsumers do not care about the response type.
      else if (!(consumer instanceof ServiceExtensionConsumer)) {
        Logging.getLogger().logError("Response missing " + TYPE + ": " + result.toString());
        return;
      }
      forwardResponse(consumer, responseType, result);
      return;
    }

    // Forward an error if the request failed
    resultElem = json.get(ERROR);
    if (resultElem != null) {
      JsonObject error;
      try {
        error = resultElem.getAsJsonObject();
      } catch (Exception e) {
        Logging.getLogger().logError("Response has invalid " + RESULT, e);
        return;
      }
      consumer.onError(new RPCError(error));
      return;
    }

    Logging.getLogger().logError("Response missing " + RESULT + " and " + ERROR);
  }
}
