// 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.RestApiServlet.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 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";

  private static final ImmutableSet<String> RESERVED_KEYS =
      ImmutableSet.of("pp", "prettyPrint", "strict", "callback", "alt", "fields", TRACE_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;
  }

  <T> boolean parse(
      T param,
      DynamicOptions pluginOptions,
      ListMultimap<String, String> in,
      HttpServletRequest req,
      HttpServletResponse res)
      throws IOException {
    CmdLineParser clp = parserFactory.create(param);
    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;
  }
}
