package me.chyxion.tigon.shiro.cas;

import java.util.Map;
import java.util.Collection;
import lombok.extern.slf4j.Slf4j;
import java.util.function.Consumer;
import org.pac4j.core.context.WebContext;
import org.pac4j.core.profile.CommonProfile;
import org.pac4j.core.credentials.TokenCredentials;
import org.pac4j.core.profile.creator.ProfileCreator;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * @author Shaun Chyxion <br>
 * chyxion@163.com <br>
 * Jun 23, 2018 16:17:53
 */
@Slf4j
public class DefaultProfileCreator implements ProfileCreator<TokenCredentials, CommonProfile> {

    @Autowired(required = false)
    private UserProfileProvider userProfileProvider;

    /**
     * {@inheritDoc}
     */
    @Override
    public CommonProfile create(final TokenCredentials credentials, final WebContext context) {
        log.debug("Create user profile from credentials [{}].", credentials);

        final CommonProfile userProfile = credentials.getUserProfile();
        if (userProfileProvider != null) {
            log.debug("User profile provider [{}] found.", userProfileProvider);
            final UserProfileProvider.UserProfile userProfileResult =
                userProfileProvider.getUserProfile(userProfile.getId());
            if (userProfileResult != null) {
                applyIfNotEmpty(userProfileResult.getRoles(), userProfile::addRoles);
                applyIfNotEmpty(userProfileResult.getPermissions(), userProfile::addPermissions);
                applyIfNotEmpty(userProfileResult.getAttrs(), userProfile::addAttributes);
                applyIfNotEmpty(userProfileResult.getAuthAttrs(), userProfile::addAuthenticationAttributes);
            }
        }
        return userProfile;
    }

    private <T> void applyIfNotEmpty(final Collection<T> data, final Consumer<Collection<T>> consumer) {
        if (data != null && !data.isEmpty()) {
            consumer.accept(data);
        }
    }

    private <K, V> void applyIfNotEmpty(final Map<K, V> data, final Consumer<Map<K, V>> consumer) {
        if (data != null && !data.isEmpty()) {
            consumer.accept(data);
        }
    }
}
