// Copyright (C) 2012 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.gerrit.server.audit;

import com.google.common.collect.ImmutableSet;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.server.audit.group.GroupAuditListener;
import com.google.gerrit.server.audit.group.GroupMemberAuditEvent;
import com.google.gerrit.server.audit.group.GroupSubgroupAuditEvent;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.sql.Timestamp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Singleton
public class AuditService {
  private static final Logger log = LoggerFactory.getLogger(AuditService.class);

  private final DynamicSet<AuditListener> auditListeners;
  private final DynamicSet<GroupAuditListener> groupAuditListeners;

  @Inject
  public AuditService(
      DynamicSet<AuditListener> auditListeners,
      DynamicSet<GroupAuditListener> groupAuditListeners) {
    this.auditListeners = auditListeners;
    this.groupAuditListeners = groupAuditListeners;
  }

  public void dispatch(AuditEvent action) {
    for (AuditListener auditListener : auditListeners) {
      auditListener.onAuditableAction(action);
    }
  }

  public void dispatchAddMembers(
      Account.Id actor,
      AccountGroup.UUID updatedGroup,
      ImmutableSet<Account.Id> addedMembers,
      Timestamp addedOn) {
    for (GroupAuditListener auditListener : groupAuditListeners) {
      try {
        GroupMemberAuditEvent event =
            GroupMemberAuditEvent.create(actor, updatedGroup, addedMembers, addedOn);
        auditListener.onAddMembers(event);
      } catch (RuntimeException e) {
        log.error("failed to log add accounts to group event", e);
      }
    }
  }

  public void dispatchDeleteMembers(
      Account.Id actor,
      AccountGroup.UUID updatedGroup,
      ImmutableSet<Account.Id> deletedMembers,
      Timestamp deletedOn) {
    for (GroupAuditListener auditListener : groupAuditListeners) {
      try {
        GroupMemberAuditEvent event =
            GroupMemberAuditEvent.create(actor, updatedGroup, deletedMembers, deletedOn);
        auditListener.onDeleteMembers(event);
      } catch (RuntimeException e) {
        log.error("failed to log delete accounts from group event", e);
      }
    }
  }

  public void dispatchAddSubgroups(
      Account.Id actor,
      AccountGroup.UUID updatedGroup,
      ImmutableSet<AccountGroup.UUID> addedSubgroups,
      Timestamp addedOn) {
    for (GroupAuditListener auditListener : groupAuditListeners) {
      try {
        GroupSubgroupAuditEvent event =
            GroupSubgroupAuditEvent.create(actor, updatedGroup, addedSubgroups, addedOn);
        auditListener.onAddSubgroups(event);
      } catch (RuntimeException e) {
        log.error("failed to log add groups to group event", e);
      }
    }
  }

  public void dispatchDeleteSubgroups(
      Account.Id actor,
      AccountGroup.UUID updatedGroup,
      ImmutableSet<AccountGroup.UUID> deletedSubgroups,
      Timestamp deletedOn) {
    for (GroupAuditListener auditListener : groupAuditListeners) {
      try {
        GroupSubgroupAuditEvent event =
            GroupSubgroupAuditEvent.create(actor, updatedGroup, deletedSubgroups, deletedOn);
        auditListener.onDeleteSubgroups(event);
      } catch (RuntimeException e) {
        log.error("failed to log delete groups from group event", e);
      }
    }
  }
}
