// 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.httpd.restapi;

import static com.google.gerrit.httpd.restapi.CorsResponder.ALLOWED_CORS_METHODS;
import static com.google.gerrit.httpd.restapi.RestApiServlet.XD_AUTHORIZATION;
import static com.google.gerrit.httpd.restapi.RestApiServlet.XD_CONTENT_TYPE;
import static com.google.gerrit.httpd.restapi.RestApiServlet.XD_METHOD;
import static com.google.gerrit.httpd.restapi.RestApiServlet.replyBinaryResult;
import static com.google.gerrit.httpd.restapi.RestApiServlet.replyError;
import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST;

import com.google.auto.value.AutoValue;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.MultimapBuilder;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.BinaryResult;
import com.google.gerrit.extensions.restapi.Url;
import com.google.gerrit.server.DynamicOptions;
import com.google.gerrit.util.cli.CmdLineParser;
import com.google.gerrit.util.http.CacheHeaders;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.io.IOException;
import java.io.StringWriter;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.kohsuke.args4j.CmdLineException;

public class ParameterParser {
  public static final String TRACE_PARAMETER = "trace";
  public static final String EXPERIMENT_PARAMETER = "experiment";

  private static final ImmutableSet<String> RESERVED_KEYS =
      ImmutableSet.of(
          "pp",
          "prettyPrint",
          "strict",
          "callback",
          "alt",
          "fields",
          TRACE_PARAMETER,
          EXPERIMENT_PARAMETER);

  @AutoValue
  public abstract static class QueryParams {
    static final String I = QueryParams.class.getName();

    static QueryParams create(
        @Nullable String accessToken,
        @Nullable String xdMethod,
        @Nullable String xdContentType,
        ImmutableListMultimap<String, String> config,
        ImmutableListMultimap<String, String> params) {
      return new AutoValue_ParameterParser_QueryParams(
          accessToken, xdMethod, xdContentType, config, params);
    }

    @Nullable
    public abstract String accessToken();

    @Nullable
    abstract String xdMethod();

    @Nullable
    abstract String xdContentType();

    abstract ImmutableListMultimap<String, String> config();

    abstract ImmutableListMultimap<String, String> params();

    boolean hasXdOverride() {
      return xdMethod() != null || xdContentType() != null;
    }
  }

  public static QueryParams getQueryParams(HttpServletRequest req) throws BadRequestException {
    QueryParams qp = (QueryParams) req.getAttribute(QueryParams.I);
    if (qp != null) {
      return qp;
    }

    String accessToken = null;
    String xdMethod = null;
    String xdContentType = null;
    ListMultimap<String, String> config = MultimapBuilder.hashKeys(4).arrayListValues().build();
    ListMultimap<String, String> params = MultimapBuilder.hashKeys().arrayListValues().build();

    String queryString = req.getQueryString();
    if (!Strings.isNullOrEmpty(queryString)) {
      for (String kvPair : Splitter.on('&').split(queryString)) {
        Iterator<String> i = Splitter.on('=').limit(2).split(kvPair).iterator();
        String key = Url.decode(i.next());
        String val = i.hasNext() ? Url.decode(i.next()) : "";

        if (XD_AUTHORIZATION.equals(key)) {
          if (accessToken != null) {
            throw new BadRequestException("duplicate " + XD_AUTHORIZATION);
          }
          accessToken = val;
        } else if (XD_METHOD.equals(key)) {
          if (xdMethod != null) {
            throw new BadRequestException("duplicate " + XD_METHOD);
          } else if (!ALLOWED_CORS_METHODS.contains(val)) {
            throw new BadRequestException("invalid " + XD_METHOD);
          }
          xdMethod = val;
        } else if (XD_CONTENT_TYPE.equals(key)) {
          if (xdContentType != null) {
            throw new BadRequestException("duplicate " + XD_CONTENT_TYPE);
          }
          xdContentType = val;
        } else if (RESERVED_KEYS.contains(key)) {
          config.put(key, val);
        } else {
          params.put(key, val);
        }
      }
    }

    qp =
        QueryParams.create(
            accessToken,
            xdMethod,
            xdContentType,
            ImmutableListMultimap.copyOf(config),
            ImmutableListMultimap.copyOf(params));
    req.setAttribute(QueryParams.I, qp);
    return qp;
  }

  private final CmdLineParser.Factory parserFactory;

  @Inject
  ParameterParser(CmdLineParser.Factory pf) {
    this.parserFactory = pf;
  }

  /**
   * Parses query parameters ({@code in}) into annotated option fields of {@code param}.
   *
   * @return true if parsing was successful. Requesting help is considered failure and returns
   *     false.
   */
  <T> boolean parse(
      T param,
      DynamicOptions pluginOptions,
      ListMultimap<String, String> in,
      HttpServletRequest req,
      HttpServletResponse res)
      throws IOException {
    if (param.getClass().getAnnotation(Singleton.class) != null) {
      // Command-line parsing mutates the object, so we can't have options on @Singleton.
      return true;
    }
    CmdLineParser clp = parserFactory.create(param);
    pluginOptions.setBean(param);
    pluginOptions.startLifecycleListeners();
    pluginOptions.parseDynamicBeans(clp);
    pluginOptions.setDynamicBeans();
    pluginOptions.onBeanParseStart();
    try {
      clp.parseOptionMap(in);
    } catch (CmdLineException | NumberFormatException e) {
      if (!clp.wasHelpRequestedByOption()) {
        replyError(req, res, SC_BAD_REQUEST, e.getMessage(), e);
        return false;
      }
    }

    if (clp.wasHelpRequestedByOption()) {
      StringWriter msg = new StringWriter();
      clp.printQueryStringUsage(req.getRequestURI(), msg);
      msg.write('\n');
      msg.write('\n');
      clp.printUsage(msg, null);
      msg.write('\n');
      CacheHeaders.setNotCacheable(res);
      replyBinaryResult(req, res, BinaryResult.create(msg.toString()).setContentType("text/plain"));
      return false;
    }
    pluginOptions.onBeanParseEnd();

    return true;
  }

  private static Set<String> query(HttpServletRequest req) {
    Set<String> params = new HashSet<>();
    if (!Strings.isNullOrEmpty(req.getQueryString())) {
      for (String kvPair : Splitter.on('&').split(req.getQueryString())) {
        params.add(Iterables.getFirst(Splitter.on('=').limit(2).split(kvPair), null));
      }
    }
    return params;
  }

  /**
   * Convert a standard URL encoded form input into a parsed JSON tree.
   *
   * <p>Given an input such as:
   *
   * <pre>
   * message=Does+not+compile.&labels.Verified=-1
   * </pre>
   *
   * which is easily created using the curl command line tool:
   *
   * <pre>
   * curl --data 'message=Does not compile.' --data labels.Verified=-1
   * </pre>
   *
   * converts to a JSON object structure that is normally expected:
   *
   * <pre>
   * {
   *   "message": "Does not compile.",
   *   "labels": {
   *     "Verified": "-1"
   *   }
   * }
   * </pre>
   *
   * This input can then be further processed into the Java input type expected by a view using
   * Gson. Here we rely on Gson to perform implicit conversion of a string {@code "-1"} to a number
   * type when the Java input type expects a number.
   *
   * <p>Conversion assumes any field name that does not contain {@code "."} will be a property of
   * the top level input object. Any field with a dot will use the first segment as the top level
   * property name naming an object, and the rest of the field name as a property in the nested
   * object.
   *
   * @param req request to parse form input from and create JSON tree.
   * @return the converted JSON object tree.
   * @throws BadRequestException the request cannot be cast, as there are conflicting definitions
   *     for a nested object.
   */
  static JsonObject formToJson(HttpServletRequest req) throws BadRequestException {
    Map<String, String[]> map = req.getParameterMap();
    return formToJson(map, query(req));
  }

  @VisibleForTesting
  static JsonObject formToJson(Map<String, String[]> map, Set<String> query)
      throws BadRequestException {
    JsonObject inputObject = new JsonObject();
    for (Map.Entry<String, String[]> ent : map.entrySet()) {
      String key = ent.getKey();
      String[] values = ent.getValue();

      if (query.contains(key) || values.length == 0) {
        // Disallow processing query parameters as input body fields.
        // Implementations of views should avoid duplicate naming.
        continue;
      }

      JsonObject obj = inputObject;
      int dot = key.indexOf('.');
      if (0 <= dot) {
        String property = key.substring(0, dot);
        JsonElement e = inputObject.get(property);
        if (e == null) {
          obj = new JsonObject();
          inputObject.add(property, obj);
        } else if (e.isJsonObject()) {
          obj = e.getAsJsonObject();
        } else {
          throw new BadRequestException(String.format("key %s conflicts with %s", key, property));
        }
        key = key.substring(dot + 1);
      }

      if (obj.get(key) != null) {
        // This error should never happen. If all form values are handled
        // together in a single pass properties are set only once. Setting
        // again indicates something has gone very wrong.
        throw new BadRequestException("invalid form input, use JSON instead");
      } else if (values.length == 1) {
        obj.addProperty(key, values[0]);
      } else {
        JsonArray list = new JsonArray();
        for (String v : values) {
          list.add(new JsonPrimitive(v));
        }
        obj.add(key, list);
      }
    }
    return inputObject;
  }
}
