package org.keycloak.quickstarts.devconf2019.app.config;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.http.client.methods.HttpUriRequest;
import org.jboss.logging.Logger;
import org.keycloak.KeycloakSecurityContext;
import org.keycloak.adapters.springsecurity.client.KeycloakClientRequestFactory;
import org.keycloak.authorization.client.AuthzClient;
import org.keycloak.authorization.client.Configuration;
import org.keycloak.jose.jws.JWSInput;
import org.keycloak.jose.jws.JWSInputException;
import org.keycloak.quickstarts.devconf2019.service.InMemoryCarsDB;
import org.keycloak.representations.AccessToken;
import org.keycloak.representations.idm.authorization.AuthorizationRequest;
import org.keycloak.representations.idm.authorization.AuthorizationResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

/**
 * @author <a href="mailto:[email protected]">Marek Posolda</a>
 */
@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class AuthzClientRequestFactory extends KeycloakClientRequestFactory {

    private static final Logger log = Logger.getLogger(AuthzClientRequestFactory.class);

    @Autowired
    public RptStore rptStore;

    @Autowired
    public HttpServletRequest servletRequest;

    @Override
    protected void postProcessHttpRequest(HttpUriRequest request) {
        KeycloakSecurityContext context = this.getKeycloakSecurityContext();

        // TODO: Ideally should do it all automatically by some provided adapter/utility
        String currentRpt = rptStore.getRpt(context);
        if (currentRpt == null) {
            // Fallback to access token
            currentRpt = context.getTokenString();
        } else {
            AccessToken parsedRpt = rptStore.getParsedRpt(context);
            if (!parsedRpt.isActive(10)) {
                // Just delete RPT and use accessToken instead. TODO: Will be good to have some "built-in" way to refresh RPT for clients
                log.info("Deleting expired RPT. Will need to obtain new when needed");
                rptStore.deleteCurrentRpt(servletRequest);
                currentRpt = context.getTokenString();
            }
        }

        request.setHeader(AUTHORIZATION_HEADER, "Bearer " + currentRpt);
    }


    @Override
    protected KeycloakSecurityContext getKeycloakSecurityContext() {
        return super.getKeycloakSecurityContext();
    }
}