/*
 * 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.oauth.v2.functions;

import static com.google.common.base.Preconditions.checkState;
import static org.jclouds.oauth.v2.OAuthConstants.ADDITIONAL_CLAIMS;
import static org.jclouds.oauth.v2.config.OAuthProperties.AUDIENCE;
import static org.jclouds.oauth.v2.config.OAuthProperties.SCOPES;
import static org.jclouds.oauth.v2.config.OAuthProperties.SIGNATURE_OR_MAC_ALGORITHM;

import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;

import javax.inject.Singleton;

import org.jclouds.Constants;
import org.jclouds.oauth.v2.config.OAuthScopes;
import org.jclouds.oauth.v2.domain.ClaimSet;
import org.jclouds.oauth.v2.domain.Header;
import org.jclouds.oauth.v2.domain.OAuthCredentials;
import org.jclouds.oauth.v2.domain.TokenRequest;
import org.jclouds.oauth.v2.domain.TokenRequestFormat;
import org.jclouds.rest.internal.GeneratedHttpRequest;

import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Supplier;
import com.google.common.reflect.Invokable;
import com.google.inject.Inject;
import com.google.inject.name.Named;

/**
 * The default authenticator.
 * <p/>
 * Builds the default token request with the following claims: iss,scope,aud,iat,exp.
 * <p/>
 * TODO scopes etc should come from the REST method and not from a global property
 */
@Singleton
public class BuildTokenRequest implements Function<GeneratedHttpRequest, TokenRequest> {

   private final String assertionTargetDescription;
   private final String signatureAlgorithm;
   private final TokenRequestFormat tokenRequestFormat;
   private final Supplier<OAuthCredentials> credentialsSupplier;
   private final long tokenDuration;

   @Inject(optional = true)
   @Named(ADDITIONAL_CLAIMS)
   protected Map<String, String> additionalClaims = Collections.emptyMap();

   @Inject(optional = true)
   @Named(SCOPES)
   protected String globalScopes = null;

   // injectable so expect tests can override with a predictable value
   @Inject(optional = true)
   protected Supplier<Long> timeSourceMillisSinceEpoch = new Supplier<Long>() {
      @Override
      public Long get() {
         return System.currentTimeMillis();
      }
   };
   
   @Inject
   public BuildTokenRequest(@Named(AUDIENCE) String assertionTargetDescription,
                            @Named(SIGNATURE_OR_MAC_ALGORITHM) String signatureAlgorithm,
                            TokenRequestFormat tokenRequestFormat, Supplier<OAuthCredentials> credentialsSupplier,
                            @Named(Constants.PROPERTY_SESSION_INTERVAL) long tokenDuration) {
      this.assertionTargetDescription = assertionTargetDescription;
      this.signatureAlgorithm = signatureAlgorithm;
      this.tokenRequestFormat = tokenRequestFormat;
      this.credentialsSupplier = credentialsSupplier;
      this.tokenDuration = tokenDuration;
   }

   @Override
   public TokenRequest apply(GeneratedHttpRequest request) {
      long now = timeSourceMillisSinceEpoch.get() / 1000;

      // fetch the token
      Header header = Header.create(signatureAlgorithm, tokenRequestFormat.type());

      Map<String, String> claims = new LinkedHashMap<String, String>();
      claims.put("iss", credentialsSupplier.get().identity);
      claims.put("scope", getOAuthScopes(request));
      claims.put("aud", assertionTargetDescription);
      claims.putAll(additionalClaims);

      checkState(claims.keySet().containsAll(tokenRequestFormat.requiredClaims()),
            "not all required claims were present");

      ClaimSet claimSet = ClaimSet.create(now, now + tokenDuration, Collections.unmodifiableMap(claims));

      return TokenRequest.create(header, claimSet);
   }

   protected String getOAuthScopes(GeneratedHttpRequest request) {
      Invokable<?, ?> invokable = request.getInvocation().getInvokable();
      
      OAuthScopes classScopes = invokable.getOwnerType().getRawType().getAnnotation(OAuthScopes.class);
      OAuthScopes methodScopes = invokable.getAnnotation(OAuthScopes.class);

      // if no annotations are present the rely on globally set scopes
      if (classScopes == null && methodScopes == null) {
         checkState(globalScopes != null, String.format("REST class or method should be annotated " +
                 "with OAuthScopes specifying required permissions. Alternatively a global property " +
                 "\"oauth.scopes\" may be set to define scopes globally. REST Class: %s, Method: %s",
                 invokable.getOwnerType(),
                 invokable.getName()));
         return globalScopes;
      }

      OAuthScopes scopes = methodScopes != null ? methodScopes : classScopes;
      return Joiner.on(",").join(scopes.value());
   }
}
