package com.eactive.eai.transformer.engine;

import java.time.Duration;

import org.apache.commons.pool2.BasePooledObjectFactory;
import org.apache.commons.pool2.ObjectPool;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;

import com.eactive.eai.transformer.SystemKeys;
import com.eactive.eai.transformer.util.Logger;

public class ParserFactory {
	private static Logger logger = Logger.getLogger("transformer");
    static ObjectPool<Parser> parserPool;

    // MAX concurrent size
    static int maxSize = 10000;
    
    static {
    	try {
    		maxSize = Integer.parseInt(System.getProperty(SystemKeys.TRANSFROMER_PARSER_CACHE_SIZE, SystemKeys.TRANSFROMER_PARSER_CACHE_DEFAULT));
    	} catch(Exception e) {
    		maxSize = Integer.parseInt(SystemKeys.TRANSFROMER_PARSER_CACHE_DEFAULT);
        }
    	logger.warn(">> ParserFactory init config");
    	logger.warn(String.format("%s = %s", SystemKeys.TRANSFROMER_PARSER_CACHE_SIZE, maxSize));
    	
        ParserObjectFactory pFactory = new ParserObjectFactory();
        
		GenericObjectPoolConfig<Parser> config = new GenericObjectPoolConfig<>();
        config.setMaxTotal(maxSize);
        config.setMaxWait(Duration.ofSeconds(3));
        config.setMaxIdle(maxSize);
        config.setMinIdle(0);
        
        parserPool = new GenericObjectPool<>(pFactory, config);
    }
    
    private ParserFactory() {
    	
    }
    
    public static int getPoolMaxSize() {
        return maxSize;
    }
    
    public static synchronized Parser getParser() throws Exception {
        return parserPool.borrowObject();
    }
    
    public static synchronized void putParser(Parser parser) throws Exception {
        parser.initSymbolTable();
        parserPool.returnObject(parser);
    }
    
    public static int activeCount() {
        return parserPool.getNumActive();
    }
}


class ParserObjectFactory extends BasePooledObjectFactory<Parser> {
    @Override
	public Parser create() throws Exception {
        Parser parser = new Parser();
        parser.initSymbolTable();
        return parser;
	}

	@Override
	public PooledObject<Parser> wrap(Parser obj) {
		return new DefaultPooledObject<>(obj);
	}	
}
