/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.hadoop.ozone.s3;

import com.google.common.annotations.VisibleForTesting;
import org.apache.hadoop.ozone.s3.exception.OS3Exception;
import org.apache.hadoop.ozone.s3.header.AuthorizationHeaderV4;
import org.apache.hadoop.ozone.s3.header.Credential;
import org.apache.kerby.util.Hex;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.core.MultivaluedMap;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.net.UnknownHostException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static java.time.temporal.ChronoUnit.SECONDS;
import static org.apache.hadoop.ozone.s3.exception.S3ErrorTable.S3_TOKEN_CREATION_ERROR;

/**
 * Parser to process AWS v4 auth request. Creates string to sign and auth
 * header. For more details refer to AWS documentation https://docs.aws
 * .amazon.com/general/latest/gr/sigv4-create-canonical-request.html.
 **/
public class AWSV4AuthParser implements AWSAuthParser {

  private final static Logger LOG =
      LoggerFactory.getLogger(AWSV4AuthParser.class);
  private MultivaluedMap<String, String> headerMap;
  private MultivaluedMap<String, String> queryMap;
  private String uri;
  private String method;
  private AuthorizationHeaderV4 v4Header;
  private String stringToSign;
  private String amzContentPayload;

  public AWSV4AuthParser(ContainerRequestContext context)
      throws OS3Exception {
    this.headerMap = context.getHeaders();
    this.queryMap = context.getUriInfo().getQueryParameters();
    try {
      this.uri = new URI(context.getUriInfo().getRequestUri()
          .getPath().replaceAll("\\/+",
              "/")).normalize().getPath();
    } catch (URISyntaxException e) {
      throw S3_TOKEN_CREATION_ERROR;
    }

    this.method = context.getMethod();
    v4Header = new AuthorizationHeaderV4(
        headerMap.getFirst(AUTHORIZATION_HEADER));
  }

  public void parse() throws Exception {
    StringBuilder strToSign = new StringBuilder();

    // According to AWS sigv4 documentation, authorization header should be
    // in following format.
    // Authorization: algorithm Credential=access key ID/credential scope,
    // SignedHeaders=SignedHeaders, Signature=signature

    // Construct String to sign in below format.
    // StringToSign =
    //    Algorithm + \n +
    //    RequestDateTime + \n +
    //    CredentialScope + \n +
    //    HashedCanonicalRequest
    String algorithm, requestDateTime, credentialScope, canonicalRequest;
    algorithm = v4Header.getAlgorithm();
    requestDateTime = headerMap.getFirst(X_AMAZ_DATE);
    Credential credential = v4Header.getCredentialObj();
    credentialScope = String.format("%s/%s/%s/%s", credential.getDate(),
        credential.getAwsRegion(), credential.getAwsService(),
        credential.getAwsRequest());

    // If the absolute path is empty, use a forward slash (/)
    uri = (uri.trim().length() > 0) ? uri : "/";
    // Encode URI and preserve forward slashes
    strToSign.append(algorithm + NEWLINE);
    strToSign.append(requestDateTime + NEWLINE);
    strToSign.append(credentialScope + NEWLINE);

    canonicalRequest = buildCanonicalRequest();
    strToSign.append(hash(canonicalRequest));
    if (LOG.isDebugEnabled()) {
      LOG.debug("canonicalRequest:[{}]", canonicalRequest);
    }

    if (LOG.isTraceEnabled()) {
      headerMap.keySet().forEach(k -> LOG.trace("Header:{},value:{}", k,
          headerMap.get(k)));
    }

    LOG.debug("StringToSign:[{}]", strToSign);
    stringToSign = strToSign.toString();
  }

  private String buildCanonicalRequest() throws OS3Exception {
    Iterable<String> parts = split("/", uri);
    List<String> encParts = new ArrayList<>();
    for (String p : parts) {
      encParts.add(urlEncode(p));
    }
    String canonicalUri = join("/", encParts);

    String canonicalQueryStr = getQueryParamString();

    StringBuilder canonicalHeaders = new StringBuilder();

    for (String header : v4Header.getSignedHeaders()) {
      List<String> headerValue = new ArrayList<>();
      canonicalHeaders.append(header.toLowerCase());
      canonicalHeaders.append(":");
      for (String originalHeader : headerMap.keySet()) {
        if (originalHeader.toLowerCase().equals(header)) {
          headerValue.add(headerMap.getFirst(originalHeader).trim());
        }
      }

      if (headerValue.size() == 0) {
        throw new RuntimeException("Header " + header + " not present in " +
            "request");
      }
      if (headerValue.size() > 1) {
        Collections.sort(headerValue);
      }

      // Set for testing purpose only to skip date and host validation.
      validateSignedHeader(header, headerValue.get(0));

      canonicalHeaders.append(join(",", headerValue));
      canonicalHeaders.append(NEWLINE);
    }

    String payloadHash;
    if (UNSIGNED_PAYLOAD.equals(
        headerMap.get(X_AMZ_CONTENT_SHA256))) {
      payloadHash = UNSIGNED_PAYLOAD;
    } else {
      payloadHash = headerMap.getFirst(X_AMZ_CONTENT_SHA256);
    }

    String signedHeaderStr = v4Header.getSignedHeaderString();
    String canonicalRequest = method + NEWLINE
        + canonicalUri + NEWLINE
        + canonicalQueryStr + NEWLINE
        + canonicalHeaders + NEWLINE
        + signedHeaderStr + NEWLINE
        + payloadHash;

    return canonicalRequest;
  }

  @VisibleForTesting
  void validateSignedHeader(String header, String headerValue)
      throws OS3Exception {
    switch (header) {
    case HOST:
      try {
        URI hostUri = new URI(headerValue);
        InetAddress.getByName(hostUri.getHost());
        // TODO: Validate if current request is coming from same host.
      } catch (UnknownHostException|URISyntaxException e) {
        LOG.error("Host value mentioned in signed header is not valid. " +
            "Host:{}", headerValue);
        throw S3_TOKEN_CREATION_ERROR;
      }
      break;
    case X_AMAZ_DATE:
      LocalDate date = LocalDate.parse(headerValue, TIME_FORMATTER);
      LocalDate now = LocalDate.now();
      if (date.isBefore(now.minus(PRESIGN_URL_MAX_EXPIRATION_SECONDS, SECONDS))
          || date.isAfter(now.plus(PRESIGN_URL_MAX_EXPIRATION_SECONDS,
          SECONDS))) {
        LOG.error("AWS date not in valid range. Request timestamp:{} should " +
                "not be older than {} seconds.", headerValue,
            PRESIGN_URL_MAX_EXPIRATION_SECONDS);
        throw S3_TOKEN_CREATION_ERROR;
      }
      break;
    case X_AMZ_CONTENT_SHA256:
      // TODO: Construct request payload and match HEX(SHA256(requestPayload))
      break;
    default:
      break;
    }
  }

  /**
   * String join that also works with empty strings.
   *
   * @return joined string
   */
  private static String join(String glue, List<String> parts) {
    StringBuilder result = new StringBuilder();
    boolean addSeparator = false;
    for (String p : parts) {
      if (addSeparator) {
        result.append(glue);
      }
      result.append(p);
      addSeparator = true;
    }
    return result.toString();
  }

  /**
   * Returns matching strings.
   *
   * @param regex Regular expression to split by
   * @param whole The string to split
   * @return pieces
   */
  private static Iterable<String> split(String regex, String whole) {
    Pattern p = Pattern.compile(regex);
    Matcher m = p.matcher(whole);
    List<String> result = new ArrayList<>();
    int pos = 0;
    while (m.find()) {
      result.add(whole.substring(pos, m.start()));
      pos = m.end();
    }
    result.add(whole.substring(pos));
    return result;
  }

  private String urlEncode(String str) {
    try {

      return URLEncoder.encode(str, UTF_8.name())
          .replaceAll("\\+", "%20")
          .replaceAll("%7E", "~");
    } catch (UnsupportedEncodingException e) {
      throw new RuntimeException(e);
    }
  }

  private String getQueryParamString() {
    List<String> params = new ArrayList<>(queryMap.keySet());

    // Sort by name, then by value
    Collections.sort(params, (o1, o2) -> o1.equals(o2) ?
        queryMap.getFirst(o1).compareTo(queryMap.getFirst(o2)) :
        o1.compareTo(o2));

    StringBuilder result = new StringBuilder();
    for (String p : params) {
      if (result.length() > 0) {
        result.append("&");
      }
      result.append(urlEncode(p));
      result.append('=');

      result.append(urlEncode(queryMap.getFirst(p)));
    }
    return result.toString();
  }

  public static String hash(String payload) throws NoSuchAlgorithmException {
    MessageDigest md = MessageDigest.getInstance("SHA-256");
    md.update(payload.getBytes(UTF_8));
    return Hex.encode(md.digest()).toLowerCase();
  }

  public String getAwsAccessId() {
    return v4Header.getAccessKeyID();
  }

  public String getSignature() {
    return v4Header.getSignature();
  }

  public String getStringToSign() throws Exception {
    return stringToSign;
  }
}
