package com.atlassian.stash.internal.user;

import com.atlassian.stash.internal.hibernate.HibernatePageUtils;
import com.atlassian.bitbucket.user.ApplicationUser;
import com.atlassian.bitbucket.permission.PermittedGroup;
import com.atlassian.bitbucket.permission.PermittedUser;
import com.atlassian.bitbucket.user.UserType;
import com.atlassian.bitbucket.util.Page;
import com.atlassian.bitbucket.util.PageRequest;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

@Repository("grantedGlobalPermissionDao")
public class HibernateGlobalPermissionDao
        extends AbstractHibernateGrantedPermissionDao<InternalGlobalPermission> implements GlobalPermissionDao {

    @Autowired
    public HibernateGlobalPermissionDao(SessionFactory sessionFactory) {
        super(sessionFactory);
    }

    @Override
    @Nonnull
    public Page<PermittedUser> findHighestPermissionPerUser(@Nonnull UserType userType, @Nullable String filter, @Nonnull PageRequest pageRequest) {
        //First, find a page of users that have repository permissions.
        //This will do two things for us:
        //1. Apply pagination
        //2. Sort the results
        Page<ApplicationUser> page = findUsersWithPermission(userType, filter, pageRequest);
        if (page.getIsLastPage() && page.getSize() == 0) {
            return HibernatePageUtils.createEmptyPage(pageRequest);
        }

        // Secondly we query for the userIds and highest permissions
        Query query = createFindHighestPermissionPerUserQuery(page, null);

        // Lastly we pair the results of the 2 queries
        return pairUsersWithPermissions(page, query);
    }

    @Override
    @Nonnull
    public Page<ApplicationUser> findUsersWithPermission(@Nonnull UserType userType, @Nonnull PageRequest request) {
        return findUsersWithPermission(userType, null, request);
    }

    @Override
    @Nonnull
    public Page<PermittedGroup> findHighestPermissionPerGroup(@Nullable String filter, @Nonnull PageRequest pageRequest) {
        Query query = createFindHighestPermissionPerGroupQuery(filter, null);
        return HibernatePageUtils.pageQuery(query, pageRequest);
    }

    @Override
    @Nonnull
    public Page<String> findGroupsWithPermission(@Nonnull PageRequest pageRequest) {
        return super.findGroupsWithPermission(pageRequest);
    }

    @Override
    public int revoke(@Nonnull InternalGlobalPermission globalPermission) {
        return createRevokeQuery(globalPermission, null).executeUpdate();
    }

}
