package com.atlassian.stash.internal.rest.enrich;

import com.atlassian.bitbucket.rest.RestMapEntity;
import com.atlassian.bitbucket.rest.enrich.AvatarEnricher;
import com.atlassian.bitbucket.rest.util.RestUtils;
import com.atlassian.bitbucket.avatar.AvatarRequest;
import com.atlassian.bitbucket.avatar.AvatarService;
import com.atlassian.bitbucket.rest.user.RestPerson;
import com.atlassian.bitbucket.rest.project.RestProject;
import com.atlassian.bitbucket.util.Page;
import com.atlassian.bitbucket.util.Timer;
import com.atlassian.bitbucket.util.TimerUtils;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.function.Function;

public class DefaultAvatarEnricher implements AvatarEnricher {

    private final AvatarService avatarService;

    public DefaultAvatarEnricher(AvatarService avatarService) {
        this.avatarService = avatarService;
    }

    public void enrich(@Nonnull Object entity, @Nullable AvatarRequest avatarRequest) {
        if (avatarRequest != null) {
            try (Timer ignored = TimerUtils.start("AvatarEnricher.enrich")) {
                setAvatarUrls(entity, avatarRequest);
            }
        }
    }

    /**
     * Examines the provided {@code entity} for {@link RestPerson} instances to populate avatar URLs for.
     * <p>
     * If the provided {@code entity} is a {@link Page Page}, {@code Iterable} or
     * {@link RestMapEntity RestMapEntity}, its values are iterated over.
     * Otherwise, if the entity is an instance of {@link RestPerson}, it has its avatar URL populated.
     *
     * @param entity  the entity to examine populate avatar URLs in
     * @param request the request describing the avatars desired by the caller
     * @see RestUtils#processEntities(Object, Function)
     */
    private void setAvatarUrls(Object entity, final AvatarRequest request) {
        RestUtils.processEntities(entity, new Function<Object, Object>() {

            @Override
            public Object apply(Object entity) {
                if (entity instanceof RestPerson) {
                    RestPerson person = (RestPerson) entity;
                    person.setAvatarUrl(avatarService.getUrlForPerson(person, request));
                } else if (entity instanceof RestProject) {
                    RestProject project = (RestProject) entity;
                    project.setAvatarUrl(avatarService.getUrlForProject(project, request));
                }

                return entity;
            }
        });
    }
}
