/*
 * 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.jclouds.s3.filters;

import static com.google.common.base.Charsets.UTF_8;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.io.BaseEncoding.base16;
import static com.google.common.io.ByteStreams.readBytes;
import static org.jclouds.crypto.Macs.asByteProcessor;
import static org.jclouds.http.utils.Queries.queryParser;
import static org.jclouds.util.Strings2.toInputStream;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.security.InvalidKeyException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.SortedMap;
import java.util.TimeZone;

import javax.inject.Inject;
import javax.xml.ws.http.HTTPException;

import com.google.common.base.Joiner;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.escape.Escaper;
import com.google.common.hash.Hashing;
import com.google.common.hash.HashingInputStream;
import com.google.common.io.ByteProcessor;
import com.google.common.io.ByteSource;
import com.google.common.io.ByteStreams;
import com.google.common.net.HttpHeaders;
import com.google.common.net.PercentEscaper;
import com.google.inject.ImplementedBy;
import org.jclouds.crypto.Crypto;
import org.jclouds.domain.Credentials;
import org.jclouds.http.HttpException;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.internal.SignatureWire;
import org.jclouds.io.Payload;
import org.jclouds.providers.ProviderMetadata;

/**
 * Common methods and properties for all AWS4 signer variants
 */
public abstract class Aws4SignerBase {
   private static final TimeZone GMT = TimeZone.getTimeZone("GMT");
   protected final DateFormat timestampFormat;
   protected final DateFormat dateFormat;

   // Do not URL-encode any of the unreserved characters that RFC 3986 defines:
   // A-Z, a-z, 0-9, hyphen (-), underscore (_), period (.), and tilde (~).
   private static final Escaper AWS_URL_PARAMETER_ESCAPER = new PercentEscaper("-_.~", false);

   private static final Escaper AWS_PATH_ESCAPER = new PercentEscaper("/-_.~", false);

   // Specifying a default for how to parse the service and region in this way allows
   // tests or other downstream services to not have to use guice overrides.
   @ImplementedBy(ServiceAndRegion.AWSServiceAndRegion.class)
   public interface ServiceAndRegion {
      String service();

      String region(String host);

      final class AWSServiceAndRegion implements ServiceAndRegion {
         private final String service;

         @Inject
         AWSServiceAndRegion(ProviderMetadata provider) {
            this(provider.getEndpoint());
         }

         AWSServiceAndRegion(String endpoint) {
            this.service = AwsHostNameUtils.parseServiceName(URI.create(checkNotNull(endpoint, "endpoint")));
         }

         @Override
         public String service() {
            return service;
         }

         @Override
         public String region(String host) {
            return AwsHostNameUtils.parseRegionName(host, service());
         }
      }
   }

   protected final String headerTag;
   protected final ServiceAndRegion serviceAndRegion;
   protected final SignatureWire signatureWire;
   protected final Supplier<Credentials> creds;
   protected final Supplier<Date> timestampProvider;
   protected final Crypto crypto;


   protected Aws4SignerBase(SignatureWire signatureWire, String headerTag,
         Supplier<Credentials> creds, Supplier<Date> timestampProvider,
         ServiceAndRegion serviceAndRegion, Crypto crypto) {
      this.signatureWire = signatureWire;
      this.headerTag = headerTag;
      this.creds = creds;
      this.timestampProvider = timestampProvider;
      this.serviceAndRegion = serviceAndRegion;
      this.crypto = crypto;
      this.timestampFormat = new SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'");
      timestampFormat.setTimeZone(GMT);
      this.dateFormat = new SimpleDateFormat("yyyyMMdd");
      dateFormat.setTimeZone(GMT);
   }

   protected String getContentType(HttpRequest request) {
      Payload payload = request.getPayload();

      // Default Content Type
      String contentType = request.getFirstHeaderOrNull(HttpHeaders.CONTENT_TYPE);
      if (payload != null
            && payload.getContentMetadata() != null
            && payload.getContentMetadata().getContentType() != null) {
         contentType = payload.getContentMetadata().getContentType();
      }
      return contentType;
   }

   protected String getContentLength(HttpRequest request) {
      Payload payload = request.getPayload();

      // Default Content Type
      String contentLength = request.getFirstHeaderOrNull(HttpHeaders.CONTENT_LENGTH);
      if (payload != null
            && payload.getContentMetadata() != null
            && payload.getContentMetadata().getContentType() != null) {
         Long length = payload.getContentMetadata().getContentLength();
         contentLength =
               length == null ? contentLength : String.valueOf(payload.getContentMetadata().getContentLength());
      }
      return contentLength;
   }

   // append all of 'x-amz-*' headers
   protected void appendAmzHeaders(HttpRequest request,
         ImmutableMap.Builder<String, String> signedHeadersBuilder) {
      for (Map.Entry<String, String> header : request.getHeaders().entries()) {
         String key = header.getKey();
         if (key.startsWith("x-" + headerTag + "-")) {
            signedHeadersBuilder.put(key.toLowerCase(), header.getValue());
         }
      }
   }

   /**
    * caluclate AWS signature key.
    * <p>
    * <code>
    * DateKey = hmacSHA256(datestamp, "AWS4"+ secretKey)
    * <br>
    * DateRegionKey = hmacSHA256(region, DateKey)
    * <br>
    * DateRegionServiceKey = hmacSHA256(service, DateRegionKey)
    * <br>
    * SigningKey = hmacSHA256("aws4_request", DateRegionServiceKey)
    * <br>
    * <p/>
    * </code>
    * </p>
    *
    * @param secretKey AWS access secret key
    * @param datestamp date yyyyMMdd
    * @param region   AWS region
    * @param service   AWS service
    * @return SigningKey
    */
   protected byte[] signatureKey(String secretKey, String datestamp, String region, String service) {
      byte[] kSecret = ("AWS4" + secretKey).getBytes(UTF_8);
      byte[] kDate = hmacSHA256(datestamp, kSecret);
      byte[] kRegion = hmacSHA256(region, kDate);
      byte[] kService = hmacSHA256(service, kRegion);
      byte[] kSigning = hmacSHA256("aws4_request", kService);
      return kSigning;
   }

   /**
    * hmac sha256
    *
    * @param toSign string to sign
    * @param key   hash key
    */
   protected byte[] hmacSHA256(String toSign, byte[] key) {
      try {
         return readBytes(toInputStream(toSign), hmacSHA256(crypto, key));
      } catch (IOException e) {
         throw new HttpException("read sign error", e);
      } catch (InvalidKeyException e) {
         throw new HttpException("invalid key", e);
      }
   }

   public static ByteProcessor<byte[]> hmacSHA256(Crypto crypto, byte[] signatureKey) throws InvalidKeyException {
      return asByteProcessor(crypto.hmacSHA256(signatureKey));
   }

   /**
    * hash input with sha256
    *
    * @param input
    * @return hash result
    * @throws HTTPException
    */
   public static byte[] hash(InputStream input) throws HTTPException {
      HashingInputStream his = new HashingInputStream(Hashing.sha256(), input);
      try {
         ByteStreams.copy(his, ByteStreams.nullOutputStream());
         return his.hash().asBytes();
      } catch (IOException e) {
         throw new HttpException("Unable to compute hash while signing request: " + e.getMessage(), e);
      }
   }

   /**
    * hash input with sha256
    *
    * @param bytes input bytes
    * @return hash result
    * @throws HTTPException
    */
   public static byte[] hash(byte[] bytes) throws HTTPException {
      try {
         return ByteSource.wrap(bytes).hash(Hashing.sha256()).asBytes();
      } catch (IOException e) {
         throw new HttpException("Unable to compute hash while signing request: " + e.getMessage(), e);
      }
   }


   /**
    * hash string (encoding UTF_8) with sha256
    *
    * @param input input stream
    * @return hash result
    * @throws HTTPException
    */
   public static byte[] hash(String input) throws HTTPException {
      return hash(new ByteArrayInputStream(input.getBytes(UTF_8)));
   }

   /**
    * Examines the specified query string parameters and returns a
    * canonicalized form.
    * <p/>
    * The canonicalized query string is formed by first sorting all the query
    * string parameters, then URI encoding both the key and value and then
    * joining them, in order, separating key value pairs with an '&'.
    *
    * @param queryString The query string parameters to be canonicalized.
    * @return A canonicalized form for the specified query string parameters.
    */
   protected String getCanonicalizedQueryString(String queryString) {
      Multimap<String, String> params = queryParser().apply(queryString);
      SortedMap<String, String> sorted = Maps.newTreeMap();
      if (params == null) {
         return "";
      }
      Iterator<Map.Entry<String, String>> pairs = params.entries().iterator();
      while (pairs.hasNext()) {
         Map.Entry<String, String> pair = pairs.next();
         String key = pair.getKey();
         String value = pair.getValue();
         sorted.put(urlEncode(key), urlEncode(value));
      }

      return Joiner.on("&").withKeyValueSeparator("=").join(sorted);
   }

   /**
    * Encode a string for use in the path of a URL; uses URLEncoder.encode,
    * (which encodes a string for use in the query portion of a URL), then
    * applies some postfilters to fix things up per the RFC. Can optionally
    * handle strings which are meant to encode a path (ie include '/'es
    * which should NOT be escaped).
    *
    * @param value the value to encode
    * @return the encoded value
    */
   public static String urlEncode(final String value) {
      if (value == null) {
         return "";
      }
      return AWS_URL_PARAMETER_ESCAPER.escape(value);
   }

   /**
    * Lowercase base 16 encoding.
    *
    * @param bytes bytes
    * @return base16 lower case hex string.
    */
   public static String hex(final byte[] bytes) {
      return base16().lowerCase().encode(bytes);
   }

   /**
    * Create a Canonical Request to sign
    * <h4>Canonical Request</h4>
    * <p>
    * <code>
    * &lt;HTTPMethod>\n
    * <br>
    * &lt;CanonicalURI>\n
    * <br>
    * &lt;CanonicalQueryString>\n
    * <br>
    * &lt;CanonicalHeaders>\n
    * <br>
    * &lt;SignedHeaders>\n
    * <br>
    * &lt;HashedPayload>
    * </code>
    * </p>
    * <p><b>HTTPMethod</b> is one of the HTTP methods, for example GET, PUT, HEAD, and DELETE.</p>
    * <p><b>CanonicalURI</b> is the URI-encoded version of the absolute path component of the URI—everything starting
    * with the "/" that follows the domain name and up to the end of the string or to the question mark character ('?')
    * if you have query string parameters.</p>
    * <p><b>CanonicalQueryString</b> specifies the URI-encoded query string parameters. You URI-encode name and values
    * individually. You must also sort the parameters in the canonical query string alphabetically by key name.
    * The sorting occurs after encoding.</p>
    * <p><b>CanonicalHeaders</b> is a list of request headers with their values. Individual header name and value pairs are
    * separated by the newline character ("\n"). Header names must be in lowercase. Header value must be trim space.
    * <br>
    * The <b>CanonicalHeaders</b> list must include the following:
    * HTTP host header.
    * If the Content-Type header is present in the request, it must be added to the CanonicalHeaders list.
    * Any x-amz-* headers that you plan to include in your request must also be added.</p>
    * <p><b>SignedHeaders</b> is an alphabetically sorted, semicolon-separated list of lowercase request header names.
    * The request headers in the list are the same headers that you included in the CanonicalHeaders string.</p>
    * <p><b>HashedPayload</b> is the hexadecimal value of the SHA256 hash of the request payload. </p>
    * <p>If there is no payload in the request, you compute a hash of the empty string as follows:
    * <code>Hex(SHA256Hash(""))</code> The hash returns the following value:
    * e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855  </p>
    *
    * @param method           http request method
    * @param endpoint         http request endpoing
    * @param signedHeaders    signed headers
    * @param timestamp        ISO8601 timestamp
    * @param credentialScope  credential scope
    * @return string to sign
    */
   protected String createStringToSign(String method, URI endpoint, Map<String, String> signedHeaders,
         String timestamp, String credentialScope, String hashedPayload) {

      // lower case header keys
      Map<String, String> lowerCaseHeaders = lowerCaseNaturalOrderKeys(signedHeaders);

      StringBuilder canonicalRequest = new StringBuilder();

      // HTTPRequestMethod + '\n' +
      canonicalRequest.append(method).append("\n");

      // CanonicalURI + '\n' +
      canonicalRequest.append(AWS_PATH_ESCAPER.escape(endpoint.getPath())).append("\n");

      // CanonicalQueryString + '\n' +
      if (endpoint.getQuery() != null) {
         canonicalRequest.append(getCanonicalizedQueryString(endpoint.getQuery()));
      }
      canonicalRequest.append("\n");

      // CanonicalHeaders + '\n' +
      for (Map.Entry<String, String> entry : lowerCaseHeaders.entrySet()) {
         canonicalRequest.append(entry.getKey()).append(':').append(entry.getValue()).append('\n');
      }
      canonicalRequest.append("\n");

      // SignedHeaders + '\n' +
      canonicalRequest.append(Joiner.on(';').join(lowerCaseHeaders.keySet())).append('\n');

      // HexEncode(Hash(Payload))
      canonicalRequest.append(hashedPayload);

      signatureWire.getWireLog().debug("<< " + canonicalRequest);

      // Create a String to Sign
      StringBuilder toSign = new StringBuilder();
      // Algorithm + '\n' +
      toSign.append("AWS4-HMAC-SHA256").append('\n');
      // RequestDate + '\n' +
      toSign.append(timestamp).append('\n');
      // CredentialScope + '\n' +
      toSign.append(credentialScope).append('\n');
      // HexEncode(Hash(CanonicalRequest))
      toSign.append(hex(hash(canonicalRequest.toString())));

      return toSign.toString();
   }

   /**
    * change the keys but keep the values in-tact.
    *
    * @param in input map to transform
    * @return immutableSortedMap with the new lowercase keys.
    */
   protected static Map<String, String> lowerCaseNaturalOrderKeys(Map<String, String> in) {
      checkNotNull(in, "input map");
      ImmutableSortedMap.Builder<String, String> returnVal = ImmutableSortedMap.<String, String>naturalOrder();
      for (Map.Entry<String, String> entry : in.entrySet())
         returnVal.put(entry.getKey().toLowerCase(Locale.US), entry.getValue());
      return returnVal.build();
   }

}
