package com.atlassian.stash.internal.audit;

import com.atlassian.bitbucket.audit.*;
import com.atlassian.bitbucket.event.permission.*;
import com.atlassian.event.api.EventListener;
import com.atlassian.event.api.EventPublisher;
import com.atlassian.bitbucket.request.RequestManager;
import com.atlassian.bitbucket.auth.AuthenticationContext;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Sets;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;

@Component
public class PermissionEventListener extends AbstractAuditEventListener {

    static final String TARGET_GLOBAL = "Global";

    @Autowired
    public PermissionEventListener(AuditEntryLoggingService auditLoggingService,
                                   RequestManager requestManager,
                                   AuthenticationContext authContext,
                                   EventPublisher eventPublisher) {
        super(auditLoggingService, requestManager, authContext, eventPublisher);
    }

    @EventListener
    public void onGlobalPermission(GlobalPermissionEvent event) throws Exception {
        AuditEntry auditEntry = createPermissionAuditEntryBuilder(event)
                .target(TARGET_GLOBAL)
                .build();
        publish(event, auditEntry, Priority.HIGH);
    }

    @EventListener
    public void onProjectPermission(ProjectPermissionEvent event) throws Exception {
        AuditEntry auditEntry = createPermissionAuditEntryBuilder(event)
                .project(event.getProject())
                .target(event.getProject().getKey())
                .build();
        publish(event, auditEntry, Sets.newHashSet(Channels.PROJECT_UI), Priority.HIGH);
    }

    @EventListener
    public void onRepositoryPermission(RepositoryPermissionEvent event) throws Exception {
        AuditEntry auditEntry = createPermissionAuditEntryBuilder(event)
                .repository(event.getRepository())
                .target(toProjectAndRepositoryString(event.getRepository()))
                .build();
        publish(event, auditEntry, Sets.newHashSet(Channels.REPOSITORY_UI), Priority.HIGH);
    }

    private AuditEntryBuilder createPermissionAuditEntryBuilder(PermissionEvent event) throws IOException {
        ImmutableMap.Builder<String, Object> builder = getMapBuilder();
        if (event instanceof PermissionModifiedEvent) {
            PermissionModifiedEvent modifiedEvent = (PermissionModifiedEvent) event;
            builder.put("old.permission", modifiedEvent.getOldValue());
            builder.put("new.permission", modifiedEvent.getNewValue());
        } else {
            builder.put("permission", event.getPermission().name());
        }
        if (event.getAffectedUser() == null && event.getAffectedGroup() == null) {
            builder.put("global", "true");
        } else {
            if (event.getAffectedUser() != null) {
                builder.put("user", event.getAffectedUser().getName());
            }
            if (event.getAffectedGroup() != null) {
                builder.put("group", event.getAffectedGroup());
            }
        }
        return createAuditEntryBuilder(event)
                .details(convertToJsonString(builder.build()));
    }

}
