/*_############################################################################
  _##
  _##  SNMP4J - TransportAuditEvent.java
  _##
  _##  Copyright (C) 2003-2026  Frank Fock (SNMP4J.org)
  _##
  _##  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 org.snmp4j.transport;

import org.snmp4j.smi.Address;

import java.util.EventObject;

/**
 * The {@code TransportAuditEvent} describes a transport level operation that is about to be executed
 * (or, for {@link TransportOperation#CLOSE}, has been executed) by a
 * {@link org.snmp4j.TransportMapping}. It is passed to all registered
 * {@link TransportAuditListener}s through
 * {@link AbstractTransportMapping#fireTransportAuditEvent(TransportAuditEvent)}, which lets the
 * listeners control (allow or deny) and audit the transport's communication.
 *
 * @author Frank Fock
 * @version 3.12.0
 * @since 3.12.0
 */
public class TransportAuditEvent extends EventObject {

    private static final long serialVersionUID = 1L;

    /**
     * The {@code TransportOperation} enumerates the transport operations that can be audited.
     */
    public enum TransportOperation {
        /**
         * A transport is about to bind and listen on a local address (open a listening port).
         */
        LISTEN,
        /**
         * A message is about to be sent to a remote address.
         */
        SEND,
        /**
         * A message has been received from a remote address and is about to be processed.
         */
        RECEIVE,
        /**
         * A listening address or a connection is being closed.
         */
        CLOSE
    }

    private final TransportOperation operation;
    private final Address peerAddress;
    private final Address localAddress;
    private final byte[] message;

    /**
     * Creates a {@code TransportAuditEvent}.
     *
     * @param source
     *    the {@link org.snmp4j.TransportMapping} that fired this event.
     * @param operation
     *    the audited {@link TransportOperation}.
     * @param peerAddress
     *    the remote address associated with the operation, or {@code null} if the operation does not
     *    refer to a remote peer (for example {@link TransportOperation#LISTEN}). For
     *    {@link TransportOperation#SEND} this is the target address, for
     *    {@link TransportOperation#RECEIVE} the source address of the received message.
     * @param localAddress
     *    the local (listen) address associated with the operation, or {@code null} if not available.
     * @param message
     *    the message associated with the operation for {@link TransportOperation#SEND} and
     *    {@link TransportOperation#RECEIVE}, or {@code null} otherwise.
     */
    public TransportAuditEvent(Object source, TransportOperation operation,
                               Address peerAddress, Address localAddress, byte[] message) {
        super(source);
        this.operation = operation;
        this.peerAddress = peerAddress;
        this.localAddress = localAddress;
        this.message = message;
    }

    /**
     * Gets the audited transport operation.
     * @return
     *    the {@link TransportOperation}.
     */
    public TransportOperation getOperation() {
        return operation;
    }

    /**
     * Gets the remote address associated with this event.
     * @return
     *    the target address for {@link TransportOperation#SEND}, the source address for
     *    {@link TransportOperation#RECEIVE}, the closed peer address for a connection
     *    {@link TransportOperation#CLOSE}, or {@code null} if no remote peer is associated with the
     *    operation.
     */
    public Address getPeerAddress() {
        return peerAddress;
    }

    /**
     * Gets the local (listen) address associated with this event.
     * @return
     *    the local address or {@code null} if not available.
     */
    public Address getLocalAddress() {
        return localAddress;
    }

    /**
     * Gets the message associated with this event.
     * @return
     *    the message bytes for {@link TransportOperation#SEND} and {@link TransportOperation#RECEIVE},
     *    or {@code null} for {@link TransportOperation#LISTEN} and {@link TransportOperation#CLOSE}.
     */
    public byte[] getMessage() {
        return message;
    }

    @Override
    public String toString() {
        return "TransportAuditEvent[" +
                "operation=" + operation +
                ", peerAddress=" + peerAddress +
                ", localAddress=" + localAddress +
                ", messageLength=" + ((message == null) ? -1 : message.length) +
                ", source=" + source +
                ']';
    }
}
