/*_############################################################################
  _## 
  _##  SNMP4J-AgentX - AgentXCommandEvent.java  
  _## 
  _##  Copyright (C) 2005-2026  Frank Fock (SNMP4J.org)
  _##  
  _##  This program is free software; you can redistribute it and/or modify
  _##  it under the terms of the GNU General Public License version 2 as 
  _##  published by the Free Software Foundation.
  _##
  _##  This program is distributed in the hope that it will be useful,
  _##  but WITHOUT ANY WARRANTY; without even the implied warranty of
  _##  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  _##  GNU General Public License for more details.
  _##
  _##  You should have received a copy of the GNU General Public License
  _##  along with this program; if not, write to the Free Software
  _##  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
  _##  MA  02110-1301  USA
  _##  
  _##########################################################################*/

package org.snmp4j.agent.agentx;

import java.io.Serial;
import java.util.EventObject;

import org.snmp4j.TransportMapping;
import org.snmp4j.TransportStateReference;
import org.snmp4j.smi.Address;
import org.snmp4j.transport.ConnectionOrientedTransportMapping;

/**
 * The {@link AgentXCommandEvent} implements an event object emitted during execution of a {@link AgentX} command.
 * @param <A>
 *     the address class of the underlying transport.
 */
public class AgentXCommandEvent<A extends Address> extends EventObject {

    @Serial
    private static final long serialVersionUID = -1607657485924685015L;

    /**
     * The address of the peer on whose behalf this event is emitted.
     */
    private final A peerAddress;
    /**
     * The connection-oriented transport mapping over which the peer communicates.
     */
    private final ConnectionOrientedTransportMapping<A> peerTransport;
    /**
     * The AgentX command (PDU) that triggered this event, or {@code null} if a parse exception occurred.
     */
    private AgentXPDU command;
    /**
     * The {@link AgentXMessageDispatcher} associated with the command.
     */
    private final AgentXMessageDispatcher dispatcher;
    /**
     * Indicates whether the command has already been processed.
     */
    private boolean processed;
    /**
     * The parse exception that occurred while decoding the command, or {@code null} if none occurred.
     */
    private AgentXParseException exception;
    /**
     * The transport state reference associated with the received command.
     */
    private final TransportStateReference tmStateReference;

    /**
     * Creates a new command event.
     * @param source
     *    the source of the event.
     * @param dispatcher
     *    the {@link AgentXMessageDispatcher} used with the command.
     * @param peerAddress
     *    the peer address.
     * @param peerTransport
     *    the peer transport.
     * @param command
     *    the command on whose behalf this event is emitted.
     * @param tmStateReference
     *    the transport mapping state reference.
     */
    public AgentXCommandEvent(Object source,
                              AgentXMessageDispatcher dispatcher,
                              A peerAddress,
                              ConnectionOrientedTransportMapping<A> peerTransport,
                              AgentXPDU command,
                              TransportStateReference tmStateReference) {
        super(source);
        this.dispatcher = dispatcher;
        this.peerTransport = peerTransport;
        this.peerAddress = peerAddress;
        this.command = command;
        this.tmStateReference = tmStateReference;
    }

    /**
     * Creates a new command event.
     * @param source
     *    the source of the event.
     * @param dispatcher
     *    the {@link AgentXMessageDispatcher} used with the command.
     * @param peerAddress
     *    the peer address.
     * @param peerTransport
     *    the peer transport.
     * @param exception
     *    the {@link AgentXParseException} occurred.
     * @param tmStateReference
     *    the transport mapping state reference.
     */
    public AgentXCommandEvent(Object source,
                              AgentXMessageDispatcher dispatcher,
                              A peerAddress,
                              ConnectionOrientedTransportMapping<A> peerTransport,
                              AgentXParseException exception,
                              TransportStateReference tmStateReference) {
        super(source);
        this.dispatcher = dispatcher;
        this.peerTransport = peerTransport;
        this.peerAddress = peerAddress;
        this.exception = exception;
        this.tmStateReference = tmStateReference;
    }

    /**
     * Gets the command.
     * @return
     *    the command emitting the event or {@code null} if an exception occurred (use {@link #getException()} then).
     */
    public AgentXPDU getCommand() {
        return command;
    }

    /**
     * Gets the peer address.
     * @return
     *    peer address.
     */
    public A getPeerAddress() {
        return peerAddress;
    }

    /**
     * Create the {@link AgentXPeer} based on peer address and peer transport.
     * @return
     *    an {@link AgentXPeer}.
     */
    public AgentXPeer<A> createAgentXPeer() {
        return new AgentXPeer<A>(peerTransport, peerAddress);
    }

    /**
     * Gets the peer transport.
     * @return
     *    a {@link ConnectionOrientedTransportMapping}.
     */
    public ConnectionOrientedTransportMapping<A> getPeerTransport() {
        return peerTransport;
    }

    /**
     * Gets the {@link AgentXMessageDispatcher}.
     * @return
     *    the AgentX message dispatcher.
     */
    public AgentXMessageDispatcher getDispatcher() {
        return dispatcher;
    }

    /**
     * Checks if the command has been processed or not.
     * @return
     *   {@code true} if the command was processed or {@code false} otheriwse.
     */
    public boolean isProcessed() {
        return processed;
    }

    /**
     * Checks if there was an exception processing the command.
     * @return
     *   {@code true} if there was an exception or {@code false} otheriwse.
     */
    public boolean isException() {
        return (exception != null);
    }

    /**
     * Gets the exception.
     * @return
     *   the exception or {@code null} if there was none.
     */
    public AgentXParseException getException() {
        return exception;
    }

    /**
     * Sets the processed flag.
     * @param done
     *    {@code true} if the command has been done, {@code false} otherwise.
     */
    public void setProcessed(boolean done) {
        this.processed = done;
    }

    /**
     * Gets the transport state reference.
     * @return
     *    a {@link TransportStateReference}.
     */
    public TransportStateReference getTmStateReference() {
        return tmStateReference;
    }

    @Override
    public String toString() {
        return "AgentXCommandEvent[" +
                "peerAddress=" + peerAddress +
                ", peerTransport=" + peerTransport +
                ", command=" + command +
                ", dispatcher=" + dispatcher +
                ", processed=" + processed +
                ", exception=" + exception +
                ", tmStateReference=" + tmStateReference +
                ']';
    }
}
