// 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.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.JSONObject;
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 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 AsyncCallback<T> cb;

    HttpCallback(AsyncCallback<T> cb) {
      this.cb = cb;
    }

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

      } else if (200 <= status && status < 300) {
        if (!isJsonBody(res)) {
          RpcStatus.INSTANCE.onRpcComplete();
          cb.onFailure(new StatusCodeException(SC_BAD_RESPONSE, "Expected "
              + JSON_TYPE + "; received Content-Type: "
              + res.getHeader("Content-Type")));
          return;
        }

        T data;
        try {
          // javac generics bug
          data = RestApi.<T>cast(parseJson(res));
        } catch (JSONException e) {
          RpcStatus.INSTANCE.onRpcComplete();
          cb.onFailure(new StatusCodeException(SC_BAD_RESPONSE,
              "Invalid JSON: " + e.getMessage()));
          return;
        }

        cb.onSuccess(data);
        RpcStatus.INSTANCE.onRpcComplete();

      } 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();
        }

        RpcStatus.INSTANCE.onRpcComplete();
        cb.onFailure(new StatusCodeException(status, msg));
      }
    }

    @Override
    public void onError(Request req, Throwable err) {
      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 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 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>(cb);
    try {
      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 put(AsyncCallback<T> cb) {
    send(PUT, 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>(cb);
    try {
      RpcStatus.INSTANCE.onRpcStart();
      String body = new JSONObject(content).toString();
      RequestBuilder req = request(method);
      req.setHeader("Content-Type", JSON_UTF8);
      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");
    }
  }
}
