/***********************************************************
Copyright (C) 2024 VeriSign, Inc.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library 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
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

http://www.verisign.com/nds/naming/namestore/techdocs.html
***********************************************************/
package com.verisign.epp.pool;

import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.PooledObjectFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.verisign.epp.transport.client.EPPSSLContext;

/**
 * Base class for the session pool factories that can be configured. The
 * concrete session pool factories will implement the concrete Commons Pool
 * PoolableObjectFactory generics class.
 */
public abstract class EPPSessionPoolableFactory implements PooledObjectFactory<EPPPooledSession> {

	/** Category for logging */
	private static Logger log = LoggerFactory.getLogger(EPPSessionPoolableFactory.class);
	/**
	 * The timeout value is not set.
	 */
	public static long TIMEOUT_UNSET = -1;
	/**
	 * Client id used during session authentication.
	 */
	protected String clientId;
	/**
	 * Password used during session authentication.
	 */
	protected String password;
	/**
	 * Session absolute timeout in milliseconds for all sessions. If both
	 * {@code minAbsoluteTimeout} and {@code maxAbsoluteTimemout} are set, they
	 * will override the setting of the {@code absoluteTimeout}.
	 */
	protected long absoluteTimeout = TIMEOUT_UNSET;
	/**
	 * Minimum absolute timeout in milliseconds. The actual absolute timeout will
	 * be randomized between the {@code minAbsoluteTimeout} and
	 * {@code maxAbsoluteTimeout}. If both {@code minAbsoluteTimeout} and
	 * {@code maxAbsoluteTimemout} are set, they will override the setting of the
	 * {@code absoluteTimeout}.
	 */
	protected long minAbsoluteTimeout = TIMEOUT_UNSET;
	/**
	 * Maximum absolute timeout in milliseconds. The actual absolute timeout will
	 * be randomized between the {@code minAbsoluteTimeout} and
	 * {@code maxAbsoluteTimeout}. If both {@code minAbsoluteTimeout} and
	 * {@code maxAbsoluteTimemout} are set, they will override the setting of the
	 * {@code absoluteTimeout}.
	 */
	protected long maxAbsoluteTimeout = TIMEOUT_UNSET;
	/**
	 * Idle timeout in milliseconds
	 */
	protected long idleTimeout = TIMEOUT_UNSET;
	/**
	 * Name or IP address of TCP server or URL of HTTP server.
	 */
	protected String serverName;
	/**
	 * Port number of TCP server. This attribute should be {@code null} when
	 * connecting to a HTTP server.
	 */
	protected Integer serverPort;
	/**
	 * Name or IP address to connect from. When {@code null} the host will be set
	 * to the loop back.
	 */
	protected String clientHost = null;
	/**
	 * SSL context information
	 */
	protected EPPSSLContext sslContext = null;
	/**
	 * Client transaction identifier generator used with login and logout
	 * commands.
	 */
	protected EPPClientTransIdGenerator clientTransIdGenerator = null;
	/**
	 * Initialize the session with the call to {@link #makeObject()} with a
	 * default value of {@code true}. This attribute also impacts the automatic
	 * call to end the session with the call to
	 * {@link #destroyObject(PooledObject)}.
	 */
	protected boolean initSessionOnMake = true;

	public EPPSessionPoolableFactory() {
	}

	/**
	 * @return Returns the clientId.
	 */
	public String getClientId() {
		return this.clientId;
	}

	/**
	 * @param clientId
	 *           The clientId to set.
	 */
	public void setClientId(String clientId) {
		this.clientId = clientId;
	}

	/**
	 * @return Returns the password.
	 */
	public String getPassword() {
		return this.password;
	}

	/**
	 * @param password
	 *           The password to set.
	 */
	public void setPassword(String password) {
		this.password = password;
	}

	/**
	 * Gets the session absolute timeout in milliseconds.
	 *
	 * @return Absolute timeout in milliseconds
	 */
	public long getAbsoluteTimeout() {
		return this.absoluteTimeout;
	}

	/**
	 * Sets the session absolute timeout in milliseconds.
	 *
	 * @param aAbsoluteTimeout
	 *           Absolute timeout in milliseconds.
	 */
	public void setAbsoluteTimeout(long aAbsoluteTimeout) {
		this.absoluteTimeout = aAbsoluteTimeout;
	}

	/**
	 * Gets the minimum session absolute timeout in milliseconds. If both
	 * {@code minAbsoluteTimeout} and {@code maxAbsoluteTimemout} are set, they
	 * will override the setting of {@code absoluteTimeout}.
	 *
	 * @return Minimum absolute timeout in milliseconds
	 */
	public long getMinAbsoluteTimeout() {
		return this.minAbsoluteTimeout;
	}

	/**
	 * Sets the minimum session absolute timeout. If both
	 * {@code minAbsoluteTimeout} and {@code maxAbsoluteTimemout} are set, they
	 * will override the setting of the {@code absoluteTimeout}.
	 *
	 * @param aMinAbsoluteTimeout
	 *           Minimum absolute timeout in milliseconds.
	 */
	public void setMinAbsoluteTimeout(long aMinAbsoluteTimeout) {
		this.minAbsoluteTimeout = aMinAbsoluteTimeout;
	}

	/**
	 * Gets the maximum session absolute timeout in milliseconds. If both
	 * {@code minAbsoluteTimeout} and {@code maxAbsoluteTimemout} are set, they
	 * will override the setting of {@code absoluteTimeout}.
	 *
	 * @return Maximum absolute timeout in milliseconds
	 */
	public long getMaxAbsoluteTimeout() {
		return this.maxAbsoluteTimeout;
	}

	/**
	 * Sets the maximum session absolute timeout. If both
	 * {@code minAbsoluteTimeout} and {@code maxAbsoluteTimemout} are set, they
	 * will override the setting of the {@code absoluteTimeout}.
	 *
	 * @param aMaxAbsoluteTimeout
	 *           Maximum absolute timeout in milliseconds.
	 */
	public void setMaxAbsoluteTimeout(long aMaxAbsoluteTimeout) {
		this.maxAbsoluteTimeout = aMaxAbsoluteTimeout;
	}

	/**
	 * Returns whether the absolute timeout will be randomized between the
	 * {@code minAbsoluteTimeout} and {@code maxAbsoluteTimemout}.
	 *
	 * @return {@code true} if the absolute timeout will be randomized;
	 *         {@code false} otherwise.
	 */
	public boolean isRandomAbsoluteTimeout() {
		log.debug("isRandomAbsoluteTimeout: minAbsoluteTimeout = " + this.minAbsoluteTimeout + ", maxAbsoluteTimeout = "
		      + this.maxAbsoluteTimeout);
		if (this.minAbsoluteTimeout != TIMEOUT_UNSET && this.maxAbsoluteTimeout != TIMEOUT_UNSET) {
			if (this.maxAbsoluteTimeout > this.minAbsoluteTimeout) {
				log.debug("isRandomAbsoluteTimeout: returning true");
				return true;
			}
			else {
				log.debug("isRandomAbsoluteTimeout: maxAbsoluteTimeout <= minAbsoluteTimeout: returning false");
				return false;
			}

		}
		else {
			log.debug("isRandomAbsoluteTimeout: maxAbsoluteTimeout or minAbsoluteTimeout not set: returning false");
			return false;
		}

	}

	/**
	 * Gets the session idle timeout.
	 *
	 * @return The idle timeout in milliseconds
	 */
	public long getIdleTimeout() {
		return this.idleTimeout;
	}

	/**
	 * Sets the session idle timeout.
	 *
	 * @param aIdleTimeout
	 *           Idle session in milliseconds
	 */
	public void setIdleTimeout(long aIdleTimeout) {
		this.idleTimeout = aIdleTimeout;
	}

	/**
	 * Gets the TCP server IP address or host name, or the URL of the HTTP
	 * server.
	 *
	 * @return Server host name, IP address, or URL
	 */
	public String getServerName() {
		return this.serverName;
	}

	/**
	 * Sets the TCP server IP address or host name or the URL of the HTTP server.
	 *
	 * @param aServerName
	 *           Server host name, IP address, or URL
	 */
	public void setServerName(String aServerName) {
		this.serverName = aServerName;
	}

	/**
	 * Gets the TCP server port number. This will be {@code null} if connecting
	 * to a HTTP server.
	 *
	 * @return TCP server port number if defined; {@code null} otherwise.
	 */
	public Integer getServerPort() {
		return this.serverPort;
	}

	/**
	 * Sets the TCP server port number.
	 *
	 * @param aServerPort
	 *           TCP server port number
	 */
	public void setServerPort(Integer aServerPort) {
		this.serverPort = aServerPort;
	}

	/**
	 * Gets the TCP server IP address or host name to connect from. A
	 * {@code null} value will use the loop back.
	 *
	 * @return Client host name or IP address if defined;{@code null} otherwise.
	 */
	public String getClientHost() {
		return this.clientHost;
	}

	/**
	 * Sets the TCP server IP address or host name to connect from. A
	 * {@code null} value will use the loop back.
	 *
	 * @param aClientHost
	 *           Client host name or IP address
	 */
	public void setClientHost(String aClientHost) {
		this.clientHost = aClientHost;
	}

	/**
	 * Gets the optional {@code EPPSSLContext} associated with the factory.
	 *
	 * @return SSL Context if defined; {@code null} otherwise
	 */
	public EPPSSLContext getSSLContext() {
		return this.sslContext;
	}

	/**
	 * Gets the optional {@code EPPSSLContext} associated with the factory.
	 *
	 * @param aSSLContext
	 *           SSL Context to use by the factory
	 */
	public void setSSLContext(EPPSSLContext aSSLContext) {
		this.sslContext = aSSLContext;
	}

	/**
	 * Gets the client transaction identifier generator object that is set.
	 *
	 * @return Client transaction identifier generator object if set;
	 *         {@code null} otherwise.
	 */
	public EPPClientTransIdGenerator getClientTransIdGenerator() {
		return this.clientTransIdGenerator;
	}

	/**
	 * Sets the client transaction identifier generator object that is used to
	 * generate client transaction identifiers for the login and logout commands.
	 *
	 * @param aClientTransIdGenerator
	 *           Client transaction identifier generator object or {@code null}
	 *           to unset the generator
	 */
	public void setClientTransIdGenerator(EPPClientTransIdGenerator aClientTransIdGenerator) {
		this.clientTransIdGenerator = aClientTransIdGenerator;
	}

	/**
	 * Initialize the session via an EPP login on the call to
	 * {@link #makeObject()}? The default value is {@code true}. This also
	 * impacts executing end session via the EPP logout on the call to
	 * {@link #destroyObject(PooledObject)}.
	 *
	 * @return {@code true} the session will be initialized via an EPP login on
	 *         the call to {@link #makeObject()}; {@code false} otherwise
	 */
	public boolean isInitSessionOnMake() {
		return initSessionOnMake;
	}

	/**
	 * Set whether to initialize the session via an EPP login on the call to
	 * {@link #makeObject()}. The default value is {@code true}. This also
	 * impacts executing end session via the EPP logout on the call to
	 * {@link #destroyObject(PooledObject)}.
	 *
	 * @param aInitSessionOnMake
	 *           {@code true} the session will be initialized via an EPP login on
	 *           the call to {@link #makeObject()}; {@code false} otherwise
	 */
	public void setInitSessionOnMake(boolean aInitSessionOnMake) {
		this.initSessionOnMake = aInitSessionOnMake;
	}
	
	

}