/*_############################################################################
  _## 
  _##  SNMP4J-AgentX - AgentXResponsePDU.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.IOException;
import java.io.Serial;
import java.io.Serializable;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.List;

import org.snmp4j.smi.VariableBinding;

import java.util.ArrayList;

/**
 * he {@link AgentXResponsePDU} represents the agentx-Regsponse-PDU defined by RFC 2741.
 */
public class AgentXResponsePDU extends AgentXPDU implements Serializable {

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

    /**
     * The value of sysUpTime returned to the command sender.
     */
    private int sysUpTime;
    /**
     * The error status reported for the response.
     */
    private short errorStatus;
    /**
     * The one-based index of the variable binding that caused the error, or zero if no error occurred.
     */
    private short errorIndex;

    /**
     * The list of variable bindings carried by this response PDU.
     */
    private List<VariableBinding> variableBindings = new ArrayList<VariableBinding>();

    /**
     * Creates a new {@link AgentXResponsePDU} from payload values.
     * @param sysUpTime
     *    the sysUpTime to return to the command sender.
     * @param errorStatus
     *    the error status.
     * @param errorIndex
     *    the error index.
     */
    public AgentXResponsePDU(int sysUpTime, short errorStatus, short errorIndex) {
        super(AGENTX_RESPONSE_PDU);
        this.sysUpTime = sysUpTime;
        this.errorIndex = errorIndex;
        this.errorStatus = errorStatus;
    }

    /**
     * Creates a {@link AgentXResponsePDU} from a {@link AgentXMessageHeader}.
     * @param header
     *    the message header.
     */
    public AgentXResponsePDU(AgentXMessageHeader header) {
        super(header);
    }

    @Override
    public void decodePayload(ByteBuffer buf, int length) throws IOException {
        sysUpTime = buf.getInt();
        errorStatus = buf.getShort();
        errorIndex = buf.getShort();
        variableBindings = Arrays.asList(AgentXProtocol.decodeVariableBindings(buf));
    }

    @Override
    protected void encodePayload(ByteBuffer buf) {
        buf.putInt(sysUpTime);
        buf.putShort(errorStatus);
        buf.putShort(errorIndex);
        AgentXProtocol.encodeVaribleBindings(buf, getVariableBindings());
    }

    @Override
    public int getPayloadLength() {
        return 2 * AgentXProtocol.AGENTX_INT_SIZE +
                AgentXProtocol.getVariableBindingsLength(getVariableBindings());
    }

    /**
     * Gets the sysUpTime value.
     * @return
     *    the sysUpTime integer value.
     */
    public int getSysUpTime() {
        return sysUpTime;
    }

    /**
     * Gets the {@link VariableBinding}s of the response PDU.
     * @return
     *    an array of {@link VariableBinding} instances.
     */
    public VariableBinding[] getVariableBindings() {
        return variableBindings.toArray(new VariableBinding[0]);
    }

    /**
     * Gets the number of variable bindings in the response PDU.
     * @return
     *    the number of variable bindings.
     */
    public int size() {
        return variableBindings.size();
    }

    /**
     * Gets the error index.
     * @return
     *    the error index.
     */
    public short getErrorIndex() {
        return errorIndex;
    }

    /**
     * Gets the error status.
     * @return
     *    the error status.
     */
    public short getErrorStatus() {
        return errorStatus;
    }

    /**
     * Sets the {@link VariableBinding} instances in the response.
     * @param variableBindings
     *    an array of {@link VariableBinding} instances.
     */
    public void setVariableBindings(VariableBinding[] variableBindings) {
        this.variableBindings = Arrays.asList(variableBindings);
    }

    /**
     * Sets the sysUpTime integer value.
     * @param sysUpTime
     *    the system up time of the command responder.
     */
    public void setSysUpTime(int sysUpTime) {
        this.sysUpTime = sysUpTime;
    }

    /**
     * Sets the error status.
     * @param errorStatus
     *    an error status as short value (= wire type).
     */
    public void setErrorStatus(short errorStatus) {
        this.errorStatus = errorStatus;
    }

    /**
     * Sets the error index.
     * @param errorIndex
     *    the error index as short value (= wire type).
     */
    public void setErrorIndex(short errorIndex) {
        this.errorIndex = errorIndex;
    }

    /**
     * Sets the error status.
     * @param errorStatus
     *    an error status as integer value (will be casted to short on the wire).
     */
    public void setErrorStatus(int errorStatus) {
        this.errorStatus = (short) errorStatus;
    }

    /**
     * Sets the error index.
     * @param errorIndex
     *    an error index as integer value (will be casted to short on the wire).
     */
    public void setErrorIndex(int errorIndex) {
        this.errorIndex = (short) errorIndex;
    }

    /**
     * Adds a {@link VariableBinding} to the response PDU.
     * @param vb
     *    a {@link VariableBinding}.
     */
    public void add(VariableBinding vb) {
        variableBindings.add(vb);
    }

    /**
     * Remove all variable bindings.
     */
    public void clear() {
        variableBindings.clear();
    }

    @Override
    protected void beforeEncode() {
    }

    @Override
    protected String toStringExtMembers() {
        return super.toStringExtMembers() + ",sysUpTime=" + sysUpTime + ",errorStatus=" +
                errorStatus + ",errorIndex=" + errorIndex + ",vbs=" + variableBindings;
    }
}
