/*_############################################################################
  _## 
  _##  SNMP4J-AgentX - AgentXPeer.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.Serializable;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import org.snmp4j.TransportMapping;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.Address;
import org.snmp4j.transport.ConnectionOrientedTransportMapping;

/**
 * An {@link AgentXPeer} represents an AgentX communication peer with its network address.
 * @param <A>
 *     the address type (depends on the used {@link TransportMapping}.
 */
public class AgentXPeer<A extends Address> implements Serializable {

    private static final long serialVersionUID = 8420653697945606497L;

    /**
     * The connection-oriented transport mapping used to communicate with this peer.
     */
    private final ConnectionOrientedTransportMapping<A> transport;
    /**
     * The network address of this peer's end-point.
     */
    private final A address;
    /**
     * The time (see {@link Date#getTime()}) when the connection to this peer was established.
     */
    private long connectionTime;
    /**
     * The message timeout in seconds used when communicating with this peer.
     */
    private int timeout;
    /**
     * A unique ID associated with this peer definition.
     */
    private Object id;
    /**
     * Indicates whether the peer is closing its transport and thus no longer accepts new connections.
     */
    private volatile boolean closing;
    /**
     * Counts the total number of parse errors that occurred on this peer.
     */
    private final AtomicInteger parseErrors = new AtomicInteger(0);

    /**
     * Creates an {@link AgentXPeer} for a transport and peer address.
     * @param transport
     *   the transport.
     * @param address
     *   the address of the peer's end-point.
     */
    public AgentXPeer(ConnectionOrientedTransportMapping<A> transport, A address) {
        this.transport = transport;
        this.address = address;
    }

    /**
     * Checks if the peer is actually closing (i.e. does not accept new connections).
     * @return
     *   {@code true} if the peer is closing its transport.
     */
    public boolean isClosing() {
        return closing;
    }

    /**
     * Gets the connection time (see {@link Date#getTime()}.
     * @return
     *    the time when the connection has been established.
     */
    public long getConnectionTime() {
        return connectionTime;
    }

    /**
     * Gets a unique ID associated with this peer definition.
     * @return
     *    its ID.
     */
    public Object getId() {
        return id;
    }

    /**
     * Gets the message timeout in seconds.
     * @return
     *    message timeout in seconds.
     */
    public int getTimeout() {
        return timeout;
    }

    /**
     * Gets the message timeout in milliseconds.
     * @return
     *    message timeout in milliseconds.
     * @since 4.0.0
     */
    public long getTimeoutMillis() {
        return TimeUnit.SECONDS.toMillis(timeout);
    }

    /**
     * Get the {@link ConnectionOrientedTransportMapping} associated with this peer.
     * @return
     *    the transport mapping.
     */
    public ConnectionOrientedTransportMapping<A> getTransport() {
        return transport;
    }

    /**
     * Gets the peer's address.
     * @return
     *    the transport address.
     */
    public A getAddress() {
        return address;
    }

    /**
     * Gets total number of parse errors on this peer.
     * @return
     *    the parse errors count.
     */
    public int getParseErrors() {
        return parseErrors.get();
    }

    /**
     * Increases the parse errors counter.
     */
    public void incParseErrors() {
        this.parseErrors.addAndGet(1);
    }

    /**
     * Sets the closing status.
     * @param closing
     *    {@code true} if the peer transport is closing.
     */
    public void setClosing(boolean closing) {
        this.closing = closing;
    }

    /**
     * Sets the connection time as long value (see {@link Date#getTime()}.
     * @param connectionTime
     *    the connection time
     */
    public void setConnectionTime(long connectionTime) {
        this.connectionTime = connectionTime;
    }

    /**
     * Sets the unique ID for this peer.
     * @param id
     *    an unique ID.
     */
    public void setId(Object id) {
        this.id = id;
    }

    /**
     * Sets the message timeout in seconds.
     * @param timeout
     *    message timeout in seconds.
     */
    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }

    @Override
    public String toString() {
        return getClass().getName() + "[transport=" + transport + ",address=" + address +
                ",connectionTime=" + connectionTime + ",timeout=" + timeout +
                ",id=" + id + ",closing=" + closing + ",parseErrors=" + parseErrors + "]";
    }

}
