package de.ids_mannheim.korap.authentication;

import java.text.ParseException;
import java.util.Map;

import com.nimbusds.jose.JOSEException;
import com.nimbusds.jwt.SignedJWT;

import de.ids_mannheim.korap.config.Attributes;
import de.ids_mannheim.korap.config.FullConfiguration;
import de.ids_mannheim.korap.config.JWTSigner;
import de.ids_mannheim.korap.constant.TokenType;
import de.ids_mannheim.korap.exceptions.KustvaktException;
import de.ids_mannheim.korap.exceptions.StatusCodes;
import de.ids_mannheim.korap.handlers.OAuthDb;
import de.ids_mannheim.korap.interfaces.AuthenticationIface;
import de.ids_mannheim.korap.interfaces.db.PersistenceClient;
import de.ids_mannheim.korap.security.context.TokenContext;
import de.ids_mannheim.korap.user.User;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;

/**
 * @author hanl
 * @date 12/11/2014
 */
public class OpenIDconnectAuthentication implements AuthenticationIface {

    private OAuthDb database;
    private FullConfiguration config;


    public OpenIDconnectAuthentication (FullConfiguration config,
                                        PersistenceClient client) {
        this.database = new OAuthDb(client);
        this.config = config;
    }


    @Override
    public TokenContext getTokenContext (String authToken)
            throws KustvaktException {
        return this.database.getContext(authToken);
    }


    @Override
    public TokenContext createTokenContext (User user, Map<String, Object> attr)
            throws KustvaktException {
        String cl_secret = (String) attr.get(Attributes.CLIENT_SECRET);
        if (cl_secret == null)
            throw new KustvaktException(StatusCodes.REQUEST_INVALID);
        attr.remove(cl_secret);
        JWTSigner signer;
        try {
            signer = new JWTSigner(cl_secret.getBytes(), config.getIssuer(),
                    config.getTokenTTL());
        }
        catch (JOSEException e1) {
            // e1.printStackTrace();
            throw new KustvaktException(StatusCodes.ILLEGAL_ARGUMENT,
                    "Failed creating JWT.", e1);
        }
        TokenContext c = new TokenContext();
        c.setUsername(user.getUsername());
        SignedJWT jwt = signer.createJWT(user, attr);
        try {
            c.setExpirationTime(
                    jwt.getJWTClaimsSet().getExpirationTime().getTime());
        }
        catch (ParseException e) {
            throw new KustvaktException(StatusCodes.ILLEGAL_ARGUMENT);
        }
        c.setTokenType(getTokenType());
        c.setToken(jwt.serialize());
        CacheManager.getInstance().getCache("id_tokens")
                .put(new Element(c.getToken(), c));
        return c;
    }


    @Override
    public void removeUserSession (String token) throws KustvaktException {
        // emit token from cache only
    }


    @Override
    public TokenContext refresh (TokenContext context)
            throws KustvaktException {
        throw new UnsupportedOperationException("method not supported");
    }


    @Override
    public TokenType getTokenType () {
        return TokenType.ID_TOKEN;
    }
}
