/*=============================================================================#
 # Copyright (c) 2009, 2021 Stephan Wahlbrink and others.
 # 
 # This program and the accompanying materials are made available under the
 # terms of the Eclipse Public License 2.0 which is available at
 # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
 # which is available at https://www.apache.org/licenses/LICENSE-2.0.
 # 
 # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
 # 
 # Contributors:
 #     Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
 #=============================================================================*/

package org.eclipse.statet.internal.rj.servi;

import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.PooledObjectState;
import org.apache.commons.pool2.impl.DefaultEvictionPolicy;
import org.apache.commons.pool2.impl.EvictionConfig;
import org.apache.commons.pool2.impl.EvictionPolicy;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;

import org.eclipse.statet.jcommons.collections.ImList;
import org.eclipse.statet.jcommons.lang.NonNullByDefault;

import org.eclipse.statet.rj.RjInvalidConfigurationException;
import org.eclipse.statet.rj.servi.pool.PoolConfig;


@NonNullByDefault
public class APool2 extends GenericObjectPool<APool2NodeHandler> {
	
	
	public static final String CLIENT_ALLOCATION_RENEW_PERIOD_MILLIS_PROPERTY_KEY= "org.eclipse.statet.rj.servi.pool.client.AllocationRenewPeriod.millis"; //$NON-NLS-1$
	
	public static final int CLIENT_ALLOCATION_RENEW_PERIOD_MILLIS_DEFAULT_VALUE= 600_000; // 10 min
	private static final int CLIENT_ALLOCATION_RENEW_PERIOD_MILLIS_MIN_VALUE= 5_000;
	
	
	private static final byte CLOSING= 2;
	private static final byte CLOSING_FINALLY= 3;
	private static final byte CLOSED= 4;
	
	
	private static final EvictionPolicy<APool2NodeHandler> EVICTION_POLICY= new DefaultEvictionPolicy<>() {
		
		@Override
		public boolean evict(final EvictionConfig config,
				final PooledObject<APool2NodeHandler> underTest, final int idleCount) {
			return (super.evict(config, underTest, idleCount)
					|| underTest.getObject().isEvictRequested(0) );
		}
		
	};
	
	
	private static GenericObjectPoolConfig<APool2NodeHandler> createAConfig(final PoolConfig config) {
		final GenericObjectPoolConfig<APool2NodeHandler> aConfig= new GenericObjectPoolConfig<>();
		
		aConfig.setLifo(true);
		aConfig.setTestOnReturn(true);
		aConfig.setTestWhileIdle(false);
		aConfig.setTestOnBorrow(false);
		aConfig.setBlockWhenExhausted(true);
		aConfig.setMaxTotal(config.getMaxTotalCount());
		aConfig.setMaxWaitMillis(config.getMaxWaitTime());
		aConfig.setMinIdle(config.getMinIdleCount());
		aConfig.setMaxIdle(config.getMaxIdleCount());
		aConfig.setMinEvictableIdleTimeMillis(0);
		aConfig.setSoftMinEvictableIdleTimeMillis(config.getMinIdleTime());
		aConfig.setTimeBetweenEvictionRunsMillis(5000);
		aConfig.setNumTestsPerEvictionRun(-4);
		aConfig.setEvictorShutdownTimeoutMillis(0);
		
		return aConfig;
	}
	
	
	private final String id;
	
	private final APool2NodeObjectFactory factory;
	
	private int clientAllocationRenewPeriodMillis;
	
	private volatile byte state;
	private boolean evicting;
	private final Object stateLock= new Object();
	
	
	public APool2(final String id, final APool2NodeObjectFactory factory, final PoolConfig config)
			throws RjInvalidConfigurationException {
		super(factory, createAConfig(config));
		this.id= id;
		this.clientAllocationRenewPeriodMillis= getClientAllocationRenewPeriodMillisDefaultValue();
		
		factory.setPool(this);
		this.factory= factory;
	}
	
	
	public String getId() {
		return this.id;
	}
	
	
	public void setConfig(final PoolConfig config) {
		setConfig(createAConfig(config));
	}
	
	@Override
	public int getMaxIdle() {
		if (this.state != 0) {
			return 0;
		}
		return super.getMaxIdle();
	}
	
	protected int getClientAllocationRenewPeriodMillisDefaultValue() throws RjInvalidConfigurationException {
		try {
			int millis= CLIENT_ALLOCATION_RENEW_PERIOD_MILLIS_DEFAULT_VALUE;
			final String s= System.getProperty(CLIENT_ALLOCATION_RENEW_PERIOD_MILLIS_PROPERTY_KEY);
			if (s != null) {
				millis= Integer.parseInt(s);
			}
			if (millis != -1 && millis < CLIENT_ALLOCATION_RENEW_PERIOD_MILLIS_MIN_VALUE) {
				throw new IllegalArgumentException(String.format("%1$s < %2$s",
						this.clientAllocationRenewPeriodMillis, CLIENT_ALLOCATION_RENEW_PERIOD_MILLIS_MIN_VALUE ));
			}
			return millis;
		}
		catch (final Exception e) {
			throw new RjInvalidConfigurationException("AllocationRenewPeriod.millis: " + e.getMessage());
		}
	}
	
	public int getClientAllocationRenewPeriodMillis() {
		return this.clientAllocationRenewPeriodMillis;
	}
	
	
	public APool2NodeHandler borrowObject(final String client) throws Exception {
		if (this.state != 0) {
			throw new IllegalStateException("Pool not open");
		}
		
		this.factory.registerArgs(client);
		try {
			return super.borrowObject();
		}
		finally {
			this.factory.clearArgs();
		}
	}
	
	
	
	public boolean isOpen() {
		return (this.state == 0);
	}
	
	@Override
	public void close() {
		throw new UnsupportedOperationException();
	}
	
	public void close(final long evictionTimeout) {
		synchronized (this.stateLock) {
			if (this.state > CLOSING) {
				return;
			}
			this.state= CLOSING;
		}
		final long evictNanos= APool2NodeHandler.evictNanos(evictionTimeout);
		final boolean evictDirect= (evictionTimeout == 0);
		
		try {
			Thread.sleep(10);
		}
		catch (final InterruptedException e) {}
		
		clear();
		
		final ImList<APool2NodeHandler> objects= this.factory.getAllObjects();
		for (final APool2NodeHandler poolObj : objects) {
			poolObj.doEvict(evictNanos, evictDirect);
		}
		
		if (this.state > CLOSING) {
			return;
		}
		setNumTestsPerEvictionRun(512);
		setTimeBetweenEvictionRunsMillis(500);
	}
	
	protected void closeFinally() {
		super.close();
		
		synchronized (this.stateLock) {
			this.state= CLOSED;
		}
	}
	
	@Override
	public void evict() throws Exception {
		synchronized (this.stateLock) {
			if (this.state > CLOSING || this.evicting) {
				return;
			}
			this.evicting= true;
		}
		try {
			int evicted;
			do {
				evicted= 0;
				final long nanos= APool2NodeHandler.safeNanos(System.nanoTime());
				
				final ImList<APool2NodeHandler> objects= this.factory.getAllObjects();
				for (final APool2NodeHandler poolObj : objects) {
					poolObj.checkClientLost(nanos);
					if (poolObj.isEvictRequested(nanos)
							&& poolObj.getPooledObject().getState() != PooledObjectState.INVALID) {
						try {
							invalidateObject(poolObj);
							evicted++;
						}
						catch (final Exception e) {}
					}
				}
			}
			while (evicted > 0);
			
			super.evict();
			
			synchronized (this.stateLock) {
				if (this.state != CLOSING || this.factory.getNumAll() > 0) {
					return;
				}
				this.state= CLOSING_FINALLY;
			}
			closeFinally();
		}
		finally {
			this.evicting= false;
		}
	}
	
	@Override
	public EvictionPolicy<APool2NodeHandler> getEvictionPolicy() {
		return EVICTION_POLICY;
	}
	
}
