/*_############################################################################
  _## 
  _##  SNMP4J - CommandResponderEvent.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;

import java.util.EventObject;

import org.snmp4j.mp.StateReference;
import org.snmp4j.security.SecurityStateReference;
import org.snmp4j.security.TsmSecurityStateReference;
import org.snmp4j.smi.Address;
import org.snmp4j.mp.PduHandle;
import org.snmp4j.smi.OctetString;

/**
 * The {@code CommandResponderEvent} is fired by the
 * {@code MessageDispatcher} to listeners that potentially can process
 * the included request, report, or trap/notification.
 *
 * @author Frank Fock
 * @author Jochen Katz
 * @version 2.0
 */
public class CommandResponderEvent<A extends Address> extends EventObject {

    private static final long serialVersionUID = 1969372060103366769L;

    private int securityModel;
    private int securityLevel;
    private int maxSizeResponsePDU;
    private PduHandle pduHandle;
    private StateReference<A> stateReference;
    private PDU pdu;
    private int messageProcessingModel;
    private byte[] securityName;
    private boolean processed;
    private A peerAddress;
    private transient TransportMapping<? super A> transportMapping;
    private TransportStateReference tmStateReference;

    /**
     * Constructs an event for processing an incoming request or notification PDU.
     *
     * @param messageDispatcher
     *         the source of the event. May be used to send response PDUs.
     * @param transportMapping
     *         the {@code TransportMapping} which received the PDU.
     * @param sourceAddress
     *         the source transport address of the SNMP message.
     * @param messageProcessingModel
     *         the message processing model ID.
     * @param securityModel
     *         the security model ID.
     * @param securityName
     *         the principal.
     * @param securityLevel
     *         the requested security level.
     * @param pduHandle
     *         the PDU handle that uniquely identifies the {@code pdu}.
     * @param pdu
     *         the SNMP request PDU to process.
     * @param maxSizeResponseScopedPDU
     *         the maximum size of a possible response PDU.
     * @param stateReference
     *         needed for responding a request, will be {@code null} for notifications.
     */
    public CommandResponderEvent(MessageDispatcher messageDispatcher,
                                 TransportMapping<? super A> transportMapping,
                                 A sourceAddress,
                                 int messageProcessingModel,
                                 int securityModel,
                                 byte[] securityName,
                                 int securityLevel,
                                 PduHandle pduHandle,
                                 PDU pdu,
                                 int maxSizeResponseScopedPDU,
                                 StateReference<A> stateReference) {
        super(messageDispatcher);
        setTransportMapping(transportMapping);
        setMessageProcessingModel(messageProcessingModel);
        setSecurityModel(securityModel);
        setSecurityName(securityName);
        setSecurityLevel(securityLevel);
        setPduHandle(pduHandle);
        setPDU(pdu);
        setMaxSizeResponsePDU(maxSizeResponseScopedPDU);
        setStateReference(stateReference);
        setPeerAddress(sourceAddress);
    }

    /**
     * Creates shallow copy of the supplied {@code CommandResponderEvent} but the source of the event is set to the
     * supplied source.
     *
     * @param source
     *         the (new) source of event copy to create.
     * @param other
     *         the {@code CommandResponderEvent} to copy.
     *
     * @since 1.1
     */
    public CommandResponderEvent(Object source, CommandResponderEvent<A> other) {
        super(source);
        setTransportMapping(other.transportMapping);
        setMessageProcessingModel(other.messageProcessingModel);
        setSecurityModel(other.securityModel);
        setSecurityName(other.securityName);
        setSecurityLevel(other.securityLevel);
        setPduHandle(other.pduHandle);
        setPDU(other.pdu);
        setMaxSizeResponsePDU(other.maxSizeResponsePDU);
        setStateReference(other.stateReference);
        setPeerAddress(other.getPeerAddress());
    }

    /**
     * Gets the message dispatcher instance that received the command (request PDU) or unconfirmed PDU like a report,
     * trap, or notification..
     *
     * @return the {@code MessageDispatcher} instance that received the command.
     */
    public MessageDispatcher getMessageDispatcher() {
        return (MessageDispatcher) super.getSource();
    }

    /**
     * Gets the security model used by the command.
     *
     * @return int
     */
    public int getSecurityModel() {
        return securityModel;
    }

    public void setSecurityModel(int securityModel) {
        this.securityModel = securityModel;
    }

    public void setSecurityLevel(int securityLevel) {
        this.securityLevel = securityLevel;
    }

    public int getSecurityLevel() {
        return securityLevel;
    }

    public void setMaxSizeResponsePDU(int maxSizeResponsePDU) {
        this.maxSizeResponsePDU = maxSizeResponsePDU;
    }

    public int getMaxSizeResponsePDU() {
        return maxSizeResponsePDU;
    }

    public void setPduHandle(org.snmp4j.mp.PduHandle pduHandle) {
        this.pduHandle = pduHandle;
    }

    public PduHandle getPduHandle() {
        return pduHandle;
    }

    public void setStateReference(org.snmp4j.mp.StateReference<A> stateReference) {
        this.stateReference = stateReference;
    }

    public org.snmp4j.mp.StateReference<A> getStateReference() {
        return stateReference;
    }

    public void setPDU(PDU pdu) {
        this.pdu = pdu;
    }

    public PDU getPDU() {
        return pdu;
    }

    public void setMessageProcessingModel(int messageProcessingModel) {
        this.messageProcessingModel = messageProcessingModel;
    }

    public int getMessageProcessingModel() {
        return messageProcessingModel;
    }

    public void setSecurityName(byte[] securityName) {
        this.securityName = securityName;
    }

    public byte[] getSecurityName() {
        return securityName;
    }

    /**
     * Sets the status of this PDU.
     *
     * @param processed
     *         If set to {@code true}, the dispatcher stops dispatching this event to other event listeners,
     *         because it has been successfully processed.
     */
    public void setProcessed(boolean processed) {
        this.processed = processed;
    }

    /**
     * Checks whether this event is already processed or not.
     *
     * @return {@code true} if this event has been processed, {@code false}
     * otherwise.
     */
    public boolean isProcessed() {
        return processed;
    }

    /**
     * Gets the transport address of the sending entity.
     *
     * @return the {@code Address} of the PDU sender.
     */
    public A getPeerAddress() {
        return peerAddress;
    }

    /**
     * Returns the transport mapping that received the PDU that triggered this event.
     *
     * @return a {@code TransportMapping} instance.
     */
    public TransportMapping<? super A> getTransportMapping() {
        return transportMapping;
    }

    /**
     * Sets the transport address of the sending entity.
     *
     * @param peerAddress
     *         the {@code Address} of the PDU sender.
     */
    public void setPeerAddress(A peerAddress) {
        this.peerAddress = peerAddress;
    }

    protected void setTransportMapping(TransportMapping<? super A> transportMapping) {
        this.transportMapping = transportMapping;
    }

    /**
     * Gets the transport model state reference as defined by RFC 5590.
     *
     * @return a {@link TransportStateReference} instance if the transport and/or the security model supports it or
     * {@code null} otherwise.
     * @since 2.0
     */
    public TransportStateReference getTmStateReference() {
        if (tmStateReference == null) {
            StateReference<A> stateReference = getStateReference();
            if (stateReference != null) {
                SecurityStateReference securityStateReference = stateReference.getSecurityStateReference();
                if (securityStateReference instanceof TsmSecurityStateReference) {
                    return ((TsmSecurityStateReference)securityStateReference).getTmStateReference();
                }
            }
        }
        return tmStateReference;
    }

    /**
     * Sets the transport model state reference as defined by RFC 5590.
     *
     * @param tmStateReference
     *         the transport model (mapping) state information associated with this command responder event.
     */
    public void setTmStateReference(TransportStateReference tmStateReference) {
        this.tmStateReference = tmStateReference;
    }

    @Override
    public String toString() {
        return "CommandResponderEvent[" +
                "securityModel=" + securityModel +
                ", securityLevel=" + securityLevel +
                ", maxSizeResponsePDU=" + maxSizeResponsePDU +
                ", pduHandle=" + pduHandle +
                ", stateReference=" + stateReference +
                ", pdu=" + pdu +
                ", messageProcessingModel=" + messageProcessingModel +
                ", securityName=" + new OctetString(securityName) +
                ", processed=" + processed +
                ", peerAddress=" + peerAddress +
                ", transportMapping=" + transportMapping +
                ", tmStateReference=" + tmStateReference +
                ']';
    }
}

