// Copyright (C) 2012 The Android Open Source Project
//
// 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.gerrit.client.rpc;

import static com.google.gwt.http.client.RequestBuilder.DELETE;
import static com.google.gwt.http.client.RequestBuilder.GET;
import static com.google.gwt.http.client.RequestBuilder.POST;
import static com.google.gwt.http.client.RequestBuilder.PUT;

import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.RpcStatus;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestBuilder.Method;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
import com.google.gwt.http.client.URL;
import com.google.gwt.json.client.JSONException;
import com.google.gwt.json.client.JSONParser;
import com.google.gwt.json.client.JSONValue;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.rpc.StatusCodeException;

/** Makes a REST API call to the server. */
public class RestApi {
  private static final int SC_UNAVAILABLE = 2;
  private static final int SC_BAD_TRANSPORT = 3;
  private static final int SC_BAD_RESPONSE = 4;
  private static final String JSON_TYPE = "application/json";
  private static final String JSON_UTF8 = JSON_TYPE + "; charset=utf-8";
  private static final String TEXT_TYPE = "text/plain";

  /**
   * Expected JSON content body prefix that prevents XSSI.
   * <p>
   * The server always includes this line as the first line of the response
   * content body when the response body is formatted as JSON. It gets inserted
   * by the server to prevent the resource from being imported into another
   * domain's page using a &lt;script&gt; tag. This line must be removed before
   * the JSON can be parsed.
   */
  private static final String JSON_MAGIC = ")]}'\n";

  /** True if err is a StatusCodeException reporting Not Found. */
  public static boolean isNotFound(Throwable err) {
    return isStatus(err, Response.SC_NOT_FOUND);
  }

  /** True if err is describing a user that is currently anonymous. */
  public static boolean isNotSignedIn(Throwable err) {
    if (err instanceof StatusCodeException) {
      StatusCodeException sce = (StatusCodeException) err;
      if (sce.getStatusCode() == Response.SC_UNAUTHORIZED) {
        return true;
      }
      return sce.getStatusCode() == Response.SC_FORBIDDEN
          && (sce.getEncodedResponse().equals("Authentication required")
              || sce.getEncodedResponse().startsWith("Must be signed-in"));
    }
    return false;
  }

  /** True if err is a StatusCodeException with a specific HTTP code. */
  public static boolean isStatus(Throwable err, int status) {
    return err instanceof StatusCodeException
        && ((StatusCodeException) err).getStatusCode() == status;
  }

  /** Is the Gerrit Code Review server likely to return this status? */
  public static boolean isExpected(int statusCode) {
    switch (statusCode) {
      case SC_UNAVAILABLE:
      case 400: // Bad Request
      case 401: // Unauthorized
      case 403: // Forbidden
      case 404: // Not Found
      case 405: // Method Not Allowed
      case 409: // Conflict
      case 412: // Precondition Failed
      case 422: // Unprocessable Entity
      case 429: // Too Many Requests (RFC 6585)
        return true;

      default:
        // Assume any other code is not expected. These may be
        // local proxy server errors outside of our control.
        return false;
    }
  }

  private static class HttpCallback<T extends JavaScriptObject>
      implements RequestCallback {
    private final boolean background;
    private final AsyncCallback<T> cb;

    HttpCallback(boolean bg, AsyncCallback<T> cb) {
      this.background = bg;
      this.cb = cb;
    }

    @Override
    public void onResponseReceived(Request req, Response res) {
      int status = res.getStatusCode();
      if (status == Response.SC_NO_CONTENT) {
        cb.onSuccess(null);
        if (!background) {
          RpcStatus.INSTANCE.onRpcComplete();
        }

      } else if (200 <= status && status < 300) {
        long start = System.currentTimeMillis();
        final T data;
        if (isTextBody(res)) {
          data = NativeString.wrap(res.getText()).cast();
        } else if (isJsonBody(res)) {
          try {
            // javac generics bug
            data = RestApi.<T>cast(parseJson(res));
          } catch (JSONException e) {
            if (!background) {
              RpcStatus.INSTANCE.onRpcComplete();
            }
            cb.onFailure(new StatusCodeException(SC_BAD_RESPONSE,
                "Invalid JSON: " + e.getMessage()));
            return;
          }
        } else {
          if (!background) {
            RpcStatus.INSTANCE.onRpcComplete();
          }
          cb.onFailure(new StatusCodeException(SC_BAD_RESPONSE, "Expected "
              + JSON_TYPE + " or " + TEXT_TYPE + "; received Content-Type: "
              + res.getHeader("Content-Type")));
          return;
        }

        Scheduler.ScheduledCommand cmd = new Scheduler.ScheduledCommand() {
          @Override
          public void execute() {
            try {
              cb.onSuccess(data);
            } finally {
              if (!background) {
                RpcStatus.INSTANCE.onRpcComplete();
              }
            }
          }
        };

        // Defer handling the response if the parse took a while.
        if ((System.currentTimeMillis() - start) > 75) {
          Scheduler.get().scheduleDeferred(cmd);
        } else {
          cmd.execute();
        }
      } else {
        String msg;
        if (isTextBody(res)) {
          msg = res.getText().trim();
        } else if (isJsonBody(res)) {
          JSONValue v;
          try {
            v = parseJson(res);
          } catch (JSONException e) {
            v = null;
          }
          if (v != null && v.isString() != null) {
            msg = v.isString().stringValue();
          } else {
            msg = trimJsonMagic(res.getText()).trim();
          }
        } else {
          msg = res.getStatusText();
        }

        if (!background) {
          RpcStatus.INSTANCE.onRpcComplete();
        }
        cb.onFailure(new StatusCodeException(status, msg));
      }
    }

    @Override
    public void onError(Request req, Throwable err) {
      if (!background) {
        RpcStatus.INSTANCE.onRpcComplete();
      }
      if (err.getMessage().contains("XmlHttpRequest.status")) {
        cb.onFailure(new StatusCodeException(
            SC_UNAVAILABLE,
            RpcConstants.C.errorServerUnavailable()));
      } else {
        cb.onFailure(new StatusCodeException(SC_BAD_TRANSPORT, err.getMessage()));
      }
    }
  }

  private StringBuilder url;
  private boolean hasQueryParams;
  private boolean background;
  private String ifNoneMatch;

  /**
   * Initialize a new API call.
   * <p>
   * By default the JSON format will be selected by including an HTTP Accept
   * header in the request.
   *
   * @param name URL of the REST resource to access, e.g. {@code "/projects/"}
   *        to list accessible projects from the server.
   */
  public RestApi(String name) {
    if (name.startsWith("/")) {
      name = name.substring(1);
    }

    url = new StringBuilder();
    url.append(GWT.getHostPageBaseURL());
    url.append(name);
  }

  public RestApi view(String name) {
    return idRaw(name);
  }

  public RestApi id(String id) {
    return idRaw(URL.encodeQueryString(id));
  }

  public RestApi id(int id) {
    return idRaw(Integer.toString(id));
  }

  public RestApi idRaw(String name) {
    if (hasQueryParams) {
      throw new IllegalStateException();
    }
    if (url.charAt(url.length() - 1) != '/') {
      url.append('/');
    }
    url.append(name);
    return this;
  }

  public RestApi addParameter(String name, String value) {
    return addParameterRaw(name, URL.encodeQueryString(value));
  }

  public RestApi addParameter(String name, String... value) {
    for (String val : value) {
      addParameter(name, val);
    }
    return this;
  }

  public RestApi addParameterTrue(String name) {
    return addParameterRaw(name, null);
  }

  public RestApi addParameter(String name, boolean value) {
    return addParameterRaw(name, value ? "t" : "f");
  }

  public RestApi addParameter(String name, int value) {
    return addParameterRaw(name, String.valueOf(value));
  }

  public RestApi addParameter(String name, Enum<?> value) {
    return addParameterRaw(name, value.name());
  }

  public RestApi addParameterRaw(String name, String value) {
    if (hasQueryParams) {
      url.append("&");
    } else {
      url.append("?");
      hasQueryParams = true;
    }
    url.append(name);
    if (value != null) {
      url.append("=").append(value);
    }
    return this;
  }

  public RestApi ifNoneMatch() {
    return ifNoneMatch("*");
  }

  public RestApi ifNoneMatch(String etag) {
    ifNoneMatch = etag;
    return this;
  }

  public RestApi background() {
    background = true;
    return this;
  }

  public String url() {
    return url.toString();
  }

  public <T extends JavaScriptObject> void get(AsyncCallback<T> cb) {
    send(GET, cb);
  }

  public <T extends JavaScriptObject> void delete(AsyncCallback<T> cb) {
    send(DELETE, cb);
  }

  private <T extends JavaScriptObject> void send(
      Method method, AsyncCallback<T> cb) {
    HttpCallback<T> httpCallback = new HttpCallback<T>(background, cb);
    try {
      if (!background) {
        RpcStatus.INSTANCE.onRpcStart();
      }
      request(method).sendRequest(null, httpCallback);
    } catch (RequestException e) {
      httpCallback.onError(null, e);
    }
  }

  public <T extends JavaScriptObject> void post(
      JavaScriptObject content,
      AsyncCallback<T> cb) {
    sendJSON(POST, content, cb);
  }

  public <T extends JavaScriptObject> void post(String content,
      AsyncCallback<T> cb) {
    sendRaw(POST, content, cb);
  }

  public <T extends JavaScriptObject> void put(AsyncCallback<T> cb) {
    send(PUT, cb);
  }

  public <T extends JavaScriptObject> void put(String content,
      AsyncCallback<T> cb) {
    sendRaw(PUT, content, cb);
  }

  public <T extends JavaScriptObject> void put(
      JavaScriptObject content,
      AsyncCallback<T> cb) {
    sendJSON(PUT, content, cb);
  }

  private <T extends JavaScriptObject> void sendJSON(
      Method method, JavaScriptObject content,
      AsyncCallback<T> cb) {
    HttpCallback<T> httpCallback = new HttpCallback<T>(background, cb);
    try {
      if (!background) {
        RpcStatus.INSTANCE.onRpcStart();
      }
      RequestBuilder req = request(method);
      req.setHeader("Content-Type", JSON_UTF8);
      req.sendRequest(str(content), httpCallback);
    } catch (RequestException e) {
      httpCallback.onError(null, e);
    }
  }

  private static native String str(JavaScriptObject jso) /*-{ return JSON.stringify(jso); }-*/;

  private <T extends JavaScriptObject> void sendRaw(Method method, String body,
      AsyncCallback<T> cb) {
    HttpCallback<T> httpCallback = new HttpCallback<T>(background, cb);
    try {
      if (!background) {
        RpcStatus.INSTANCE.onRpcStart();
      }
      RequestBuilder req = request(method);
      req.setHeader("Content-Type", TEXT_TYPE);
      req.sendRequest(body, httpCallback);
    } catch (RequestException e) {
      httpCallback.onError(null, e);
    }
  }

  private RequestBuilder request(Method method) {
    RequestBuilder req = new RequestBuilder(method, url());
    if (ifNoneMatch != null) {
      req.setHeader("If-None-Match", ifNoneMatch);
    }
    req.setHeader("Accept", JSON_TYPE);
    if (Gerrit.getXGerritAuth() != null) {
      req.setHeader("X-Gerrit-Auth", Gerrit.getXGerritAuth());
    }
    return req;
  }

  private static boolean isJsonBody(Response res) {
    return isContentType(res, JSON_TYPE);
  }

  private static boolean isTextBody(Response res) {
    return isContentType(res, TEXT_TYPE);
  }

  private static boolean isContentType(Response res, String want) {
    String type = res.getHeader("Content-Type");
    if (type == null) {
      return false;
    }
    int semi = type.indexOf(';');
    if (semi >= 0) {
      type = type.substring(0, semi).trim();
    }
    return want.equals(type);
  }

  private static JSONValue parseJson(Response res)
      throws JSONException {
    String json = trimJsonMagic(res.getText());
    if (json.isEmpty()) {
      throw new JSONException("response was empty");
    }
    return JSONParser.parseStrict(json);
  }

  private static String trimJsonMagic(String json) {
    if (json.startsWith(JSON_MAGIC)) {
      json = json.substring(JSON_MAGIC.length());
    }
    return json;
  }

  @SuppressWarnings("unchecked")
  private static <T extends JavaScriptObject> T cast(JSONValue val) {
    if (val.isObject() != null) {
      return (T) val.isObject().getJavaScriptObject();
    } else if (val.isArray() != null) {
      return (T) val.isArray().getJavaScriptObject();
    } else if (val.isString() != null) {
      return (T) NativeString.wrap(val.isString().stringValue());
    } else if (val.isNull() != null) {
      return null;
    } else {
      throw new JSONException("unsupported JSON type");
    }
  }
}
