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

import com.atlassian.stash.internal.page.PageConstants;
import com.atlassian.stash.internal.project.InternalPersonalProject;
import com.atlassian.stash.internal.project.InternalProjectService;
import com.atlassian.stash.internal.web.soy.StashSoyResponseBuilder;
import com.atlassian.bitbucket.project.PersonalProject;
import com.atlassian.bitbucket.project.Project;
import com.atlassian.bitbucket.pull.PullRequest;
import com.atlassian.bitbucket.pull.PullRequestService;
import com.atlassian.bitbucket.repository.Repository;
import com.atlassian.bitbucket.repository.RepositoryService;
import com.atlassian.bitbucket.user.ApplicationUser;
import com.atlassian.bitbucket.user.UserService;
import com.atlassian.bitbucket.user.UserType;
import com.atlassian.bitbucket.util.NumberUtils;
import com.opensymphony.sitemesh.Content;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * @since 3.5
 */
@Component
public class SiteMeshDataContributor {

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

    private final InternalProjectService projectService;
    private final PullRequestService pullRequestService;
    private final RepositoryService repositoryService;
    private final UserService userService;

    @Value(PageConstants.MAX_CHANGES)
    private int maxChanges;

    @Autowired
    public SiteMeshDataContributor(InternalProjectService projectService, PullRequestService pullRequestService,
                                   RepositoryService repositoryService, UserService userService) {
        this.projectService = projectService;
        this.pullRequestService = pullRequestService;
        this.repositoryService = repositoryService;
        this.userService = userService;
    }

    public void contribute(Content content, StashSoyResponseBuilder dataBuilder) {
        String connectHostUrl = content.getProperty("meta.connectHostUrl");
        String projectKey = content.getProperty("meta.projectKey");
        String repoSlug = content.getProperty("meta.repositorySlug");
        String pullRequestId = content.getProperty("meta.pullRequestId");
        Integer userId = NumberUtils.parse(content.getProperty("meta.userId"), null, null); // this is the user in the page (eg profile, repo owner), _not_ the logged in user
        String userSlug = content.getProperty("meta.userSlug"); // this is the user in the page (eg profile, repo owner), _not_ the logged in user

        if (connectHostUrl != null) {
            dataBuilder.put("connectHostUrl", connectHostUrl);
        }

        ApplicationUser user = null;
        if (userId != null) {
            user = userService.getUserById(userId);
        } else if (StringUtils.isNotEmpty(userSlug)) {
            user = userService.getUserBySlug(userSlug);
        }

        if (user != null) {
            dataBuilder.put("user", user);
            if (user.getType() == UserType.NORMAL) {
                String userProjectKey = InternalPersonalProject.createPersonalProjectKey(user);
                if (projectKey != null && !userProjectKey.equalsIgnoreCase(projectKey)) {
                    log.warn("Both userSlug and projectKey were specified to the decorator, user's personal project {} is going to stomp {}",
                            userProjectKey, projectKey);
                }
                PersonalProject project = projectService.getPersonalProject(user);
                dataBuilder.putProject(project);
            }
        } else if (!StringUtils.isEmpty(projectKey)) {
            Project project = null;
            if (!StringUtils.isEmpty(repoSlug)) {
                Repository repo = repositoryService.getBySlug(projectKey, repoSlug);
                if (repo != null) {
                    project = repo.getProject();
                    if (!StringUtils.isEmpty(pullRequestId)) {
                        PullRequest pullRequest = pullRequestService.getById(repo.getId(), Long.parseLong(pullRequestId));
                        if (pullRequest != null) {
                            dataBuilder.putPullRequest(pullRequest);
                        }
                        dataBuilder.put("maxChanges", maxChanges);
                    }
                    dataBuilder.putRepository(repo);
                }
            } else {
                project = projectService.getByKey(projectKey);
            }
            if (project != null) {
                dataBuilder.putProject(project);
            }
        }
    }
}
