package com.atlassian.stash.internal.web.users;

import com.atlassian.bitbucket.i18n.I18nService;
import com.atlassian.stash.internal.avatar.InternalAvatarService;
import com.atlassian.stash.internal.project.InternalProjectService;
import com.atlassian.stash.internal.web.util.ResponseFactory;
import com.atlassian.bitbucket.nav.NavBuilder;
import com.atlassian.bitbucket.user.ApplicationUser;
import com.atlassian.bitbucket.auth.AuthenticationContext;
import com.atlassian.bitbucket.user.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Nonnull;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Controller
@RequestMapping("/users/{userSlug}")
public class UserProfileController extends AbstractProfileController {

    private final InternalAvatarService avatarService;
    private final NavBuilder navBuilder;

    @Autowired
    public UserProfileController(I18nService i18nService, AuthenticationContext authenticationContext,
                                 InternalProjectService projectService, UserService userService,
                                 InternalAvatarService avatarService, NavBuilder navBuilder) {
        super(i18nService, authenticationContext, projectService, userService);

        this.avatarService = avatarService;
        this.navBuilder = navBuilder;
    }

    @RequestMapping(value = "/avatar.png", method = RequestMethod.GET, produces = MediaType.IMAGE_PNG_VALUE)
    public void retrieveAvatar(@PathVariable("userSlug") String userSlug,
                               @RequestParam(defaultValue = "256", value = "s") int size,
                               HttpServletRequest request,
                               HttpServletResponse response) throws IOException {
        ApplicationUser user = userService.getUserBySlug(userSlug);
        if (user == null) {
            //To allow user avatars to be shown in non-authenticated contexts (public repositories), they cannot
            //be permission checked. That means the server needs to do the next best thing and respond consistently
            //for nonexistent users.
            //
            //This still leaks user existence (if they have a non-default avatar, the user definitely exists), but
            //it is a weaker leak because users that do not exist still return default avatars.
            streamAvatar(avatarService.getUserDefault(size), request, response);
        } else {
            retrieveAvatar(user, size, request, response);
        }
    }

    @RequestMapping(method = RequestMethod.GET)
    public ModelAndView showProfile(@PathVariable("userSlug") String slug) {
        return showProfile(getUser(slug));
    }

    @RequestMapping(value = "/avatar.png", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, method = RequestMethod.POST)
    public ResponseEntity<Void> uploadAvatar(@PathVariable("userSlug") String slug, @RequestParam("avatar") String uri) {
        ApplicationUser user = getUser(slug);
        userService.updateAvatar(user, uri);
        return ResponseFactory.created(navBuilder.user(user).avatar(256).buildAbsolute());
    }

    @Nonnull
    private ApplicationUser getUser(String slug) {
        ApplicationUser user = userService.getUserBySlug(slug);
        if (user == null) {
            throw newNoSuchUserBySlugException(slug);
        }

        return user;
    }
}
