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

import static com.google.common.base.Charsets.UTF_8;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.Ordering.natural;
import static com.google.common.io.BaseEncoding.base64;
import static com.google.common.io.ByteStreams.readBytes;
import static org.jclouds.aws.filters.FormSignerUtils.getAnnotatedApiVersion;
import static org.jclouds.aws.reference.FormParameters.ACTION;
import static org.jclouds.aws.reference.FormParameters.AWS_ACCESS_KEY_ID;
import static org.jclouds.aws.reference.FormParameters.SECURITY_TOKEN;
import static org.jclouds.aws.reference.FormParameters.SIGNATURE;
import static org.jclouds.aws.reference.FormParameters.SIGNATURE_METHOD;
import static org.jclouds.aws.reference.FormParameters.SIGNATURE_VERSION;
import static org.jclouds.aws.reference.FormParameters.TIMESTAMP;
import static org.jclouds.aws.reference.FormParameters.VERSION;
import static org.jclouds.crypto.Macs.asByteProcessor;
import static org.jclouds.http.utils.Queries.encodeQueryLine;
import static org.jclouds.http.utils.Queries.queryParser;
import static org.jclouds.util.Strings2.toInputStream;

import java.util.Comparator;
import java.util.Set;

import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Provider;

import org.jclouds.Constants;
import org.jclouds.aws.domain.SessionCredentials;
import org.jclouds.crypto.Crypto;
import org.jclouds.date.TimeStamp;
import org.jclouds.domain.Credentials;
import org.jclouds.http.HttpException;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpRequestFilter;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.internal.SignatureWire;
import org.jclouds.logging.Logger;
import org.jclouds.rest.RequestSigner;
import org.jclouds.rest.annotations.ApiVersion;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap;
import com.google.common.collect.TreeMultimap;
import com.google.common.io.ByteProcessor;
import com.google.common.net.HttpHeaders;
import com.google.inject.ImplementedBy;

@ImplementedBy(FormSigner.FormSignerV2.class)
public interface FormSigner extends HttpRequestFilter {

   static final class FormSignerV2 implements FormSigner, RequestSigner {

      public static final Set<String> mandatoryParametersForSignature = ImmutableSet
            .of(ACTION, SIGNATURE_METHOD, SIGNATURE_VERSION, VERSION);

      private final SignatureWire signatureWire;
      private final String apiVersion;
      private final Supplier<Credentials> creds;
      private final Provider<String> dateService;
      private final Crypto crypto;
      private final HttpUtils utils;

      @Resource @Named(Constants.LOGGER_SIGNATURE)
      private Logger signatureLog = Logger.NULL;

      @Inject FormSignerV2(SignatureWire signatureWire, @ApiVersion String apiVersion,
            @org.jclouds.location.Provider Supplier<Credentials> creds, @TimeStamp Provider<String> dateService,
            Crypto crypto, HttpUtils utils) {
         this.signatureWire = signatureWire;
         this.apiVersion = apiVersion;
         this.creds = creds;
         this.dateService = dateService;
         this.crypto = crypto;
         this.utils = utils;
      }

      public HttpRequest filter(HttpRequest request) throws HttpException {
         checkNotNull(request.getFirstHeaderOrNull(HttpHeaders.HOST), "request is not ready to sign; host not present");
         Multimap<String, String> decodedParams = queryParser().apply(request.getPayload().getRawContent().toString());
         Optional<String> optAnnotatedVersion = getAnnotatedApiVersion(request);
         String version;
         if (optAnnotatedVersion.isPresent()) {
            String annotatedVersion = optAnnotatedVersion.get();
            version = annotatedVersion.compareTo(apiVersion) > 0 ? annotatedVersion : apiVersion;
         } else {
            version = apiVersion;
         }
         decodedParams.replaceValues(VERSION, ImmutableSet.of(version));
         addSigningParams(decodedParams);
         validateParams(decodedParams);
         String stringToSign = createStringToSign(request, decodedParams);
         String signature = sign(stringToSign);
         addSignature(decodedParams, signature);
         request = setPayload(request, decodedParams);
         utils.logRequest(signatureLog, request, "<<");
         return request;
      }

      HttpRequest setPayload(HttpRequest request, Multimap<String, String> decodedParams) {
         String queryLine = buildQueryLine(decodedParams);
         request.setPayload(queryLine);
         request.getPayload().getContentMetadata().setContentType("application/x-www-form-urlencoded");
         return request;
      }

      private static final Comparator<String> actionFirstAccessKeyLast = new Comparator<String>() {
         static final int LEFT_IS_GREATER = 1;
         static final int RIGHT_IS_GREATER = -1;

         @Override
         public int compare(String left, String right) {
            if (Objects.equal(left, right)) {
               return 0;
            }
            if ("Action".equals(right) || "AWSAccessKeyId".equals(left)) {
               return LEFT_IS_GREATER;
            }
            if ("Action".equals(left) || "AWSAccessKeyId".equals(right)) {
               return RIGHT_IS_GREATER;
            }
            return natural().compare(left, right);
         }
      };

      private static String buildQueryLine(Multimap<String, String> decodedParams) {
         Multimap<String, String> sortedParams = TreeMultimap.create(actionFirstAccessKeyLast, natural());
         sortedParams.putAll(decodedParams);
         return encodeQueryLine(sortedParams);
      }

      @VisibleForTesting void validateParams(Multimap<String, String> params) {
         for (String parameter : mandatoryParametersForSignature) {
            checkState(params.containsKey(parameter), "parameter " + parameter + " is required for signature");
         }
      }

      @VisibleForTesting void addSignature(Multimap<String, String> params, String signature) {
         params.replaceValues(SIGNATURE, ImmutableList.of(signature));
      }

      @VisibleForTesting
      public String sign(String toSign) {
         String signature;
         try {
            ByteProcessor<byte[]> hmacSHA256 = asByteProcessor(
                  crypto.hmacSHA256(creds.get().credential.getBytes(UTF_8)));
            signature = base64().encode(readBytes(toInputStream(toSign), hmacSHA256));
            if (signatureWire.enabled())
               signatureWire.input(toInputStream(signature));
         } catch (Exception e) {
            throw new HttpException("error signing request", e);
         }
         return signature;
      }

      @VisibleForTesting
      public String createStringToSign(HttpRequest request, Multimap<String, String> decodedParams) {
         utils.logRequest(signatureLog, request, ">>");
         StringBuilder stringToSign = new StringBuilder();
         // StringToSign = HTTPVerb + "\n" +
         stringToSign.append(request.getMethod()).append("\n");
         // ValueOfHostHeaderInLowercase + "\n" +
         stringToSign.append(request.getFirstHeaderOrNull(HttpHeaders.HOST).toLowerCase()).append("\n");
         // HTTPRequestURI + "\n" +
         stringToSign.append(request.getEndpoint().getPath()).append("\n");
         // CanonicalizedFormString <from the preceding step>
         stringToSign.append(buildCanonicalizedString(decodedParams));
         if (signatureWire.enabled())
            signatureWire.output(stringToSign.toString());
         return stringToSign.toString();
      }

      @VisibleForTesting String buildCanonicalizedString(Multimap<String, String> decodedParams) {
         // note that aws wants to percent encode the canonicalized string without skipping '/' and '?'
         return encodeQueryLine(TreeMultimap.create(decodedParams), ImmutableList.<Character>of());
      }

      @VisibleForTesting void addSigningParams(Multimap<String, String> params) {
         params.removeAll(SIGNATURE);
         params.removeAll(SECURITY_TOKEN);
         Credentials current = creds.get();
         if (current instanceof SessionCredentials) {
            params.put(SECURITY_TOKEN, SessionCredentials.class.cast(current).getSessionToken());
         }
         params.replaceValues(SIGNATURE_METHOD, ImmutableList.of("HmacSHA256"));
         params.replaceValues(SIGNATURE_VERSION, ImmutableList.of("2"));
         params.replaceValues(TIMESTAMP, ImmutableList.of(dateService.get()));
         params.replaceValues(AWS_ACCESS_KEY_ID, ImmutableList.of(creds.get().identity));
      }

      public String createStringToSign(HttpRequest input) {
         return createStringToSign(input, queryParser().apply(input.getPayload().getRawContent().toString()));
      }
   }
}
