package com.eactive.eai.adapter.http.client;

import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.lang.StringUtils;

import com.eactive.eai.adapter.AdapterGroupVO;
import com.eactive.eai.adapter.AdapterManager;
import com.eactive.eai.adapter.AdapterPropManager;
import com.eactive.eai.adapter.AdapterVO;
import com.eactive.eai.common.util.Logger;
import com.eactive.eai.httpouttlsinfo.HttpOutTlsInfoManager;
import com.eactive.eai.httpouttlsinfo.HttpOutTlsInfoVO;

public class HttpClientAdapterServiceFactory {
	private static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
	private static ConcurrentHashMap<String, HttpClientAdapterService> adapters = new ConcurrentHashMap<>();
	private static ConcurrentHashMap<String, String> adapterClass = new ConcurrentHashMap<>();
	
	private HttpClientAdapterServiceFactory() {
		super();
	}

	public static HttpClientAdapterService createFactory(String className, String adapterGroupName, String adapterName) throws Exception {
		HttpClientAdapterService service = null;
		if (adapters.containsKey(adapterName)) {
			service = adapters.get(adapterName);
			if (className.equals(adapterClass.get(adapterName))) {
				return service;
			}
			else {
				service.close();
				service = null;
			}
		}

		try {
			Class cl = Class.forName(className);
			service = (HttpClientAdapterService) cl.newInstance();
			
			boolean useMtls = false;
			
			int maxTotalConnections = HttpClientAdapterServiceKey.DEFAULT_MAX_TOTAL_CONNECTIONS;
			int maxHostConnections = HttpClientAdapterServiceKey.DEFAULT_MAX_CONNECTION_PER_HOST;
			AdapterVO adapterVo = AdapterManager.getInstance().getAdapterVO(adapterGroupName, adapterName);
			AdapterPropManager manager = AdapterPropManager.getInstance();
			Properties outboundProp = manager.getProperties(adapterVo.getPropGroupName());
			
			try {
				maxTotalConnections = Integer.parseInt(outboundProp.getProperty(HttpClientAdapterServiceKey.MAX_TOTAL_CONNECTIONS)); 
			}
			catch(NumberFormatException ex) {
				maxTotalConnections = HttpClientAdapterServiceKey.DEFAULT_MAX_TOTAL_CONNECTIONS;
				if(logger.isWarn()) {
					logger.warn("HttpClientAdapterService. : {}, adatperName : {} UseDefault {}={}, {}"
							, className, adapterName,HttpClientAdapterServiceKey.MAX_TOTAL_CONNECTIONS, maxTotalConnections, ex.toString());
				}
			}
			
			try {
				maxHostConnections = Integer.parseInt(outboundProp.getProperty(HttpClientAdapterServiceKey.MAX_CONNECTION_PER_HOST));
			}
			catch(NumberFormatException ex) {
				maxHostConnections = HttpClientAdapterServiceKey.DEFAULT_MAX_CONNECTION_PER_HOST;
				if(logger.isWarn()) {
					logger.warn("HttpClientAdapterService. : {}, adatperName : {} UseDefault {}={}, {}"
							, className, adapterName,HttpClientAdapterServiceKey.MAX_CONNECTION_PER_HOST, maxHostConnections, ex.toString());
				}
			}
			
			// clientID -> mTLS 인증정보 획득
			useMtls = StringUtils.equalsIgnoreCase(outboundProp.getProperty(HttpClientAdapterServiceKey.USE_MTLS),"Y");
			
			AdapterGroupVO adapterGroup = AdapterManager.getInstance().getAdapterGroup(adapterGroupName);
			// outboundProp.getProperty(HttpClientAdapterServiceKey.CLIENT_ID);
			String clientId = adapterGroup.getClientId();
			
			if(logger.isInfo()) {
				logger.info("MTLS adapterName. : {}, useMtls. : {}, clientId : {}", adapterName, useMtls, clientId);
			}
			HttpOutTlsInfoVO mtlsInfo = null;
			if(useMtls) {
				HttpOutTlsInfoManager tlsManager = HttpOutTlsInfoManager.getInstance();
				if(StringUtils.isNotEmpty(clientId)) {
					mtlsInfo = tlsManager.getHttpOutTlsInfo(clientId);
				}
			}
//						keyStorePath = outboundProp.getProperty(HttpClientAdapterServiceKey.KEYSTORE_PATH);
//						keyStorePassword = outboundProp.getProperty(HttpClientAdapterServiceKey.KEYSTORE_PWD);
//						trustStorePath = outboundProp.getProperty(HttpClientAdapterServiceKey.TRUSTSTORE_PATH);
//						trustStorePassword = outboundProp.getProperty(HttpClientAdapterServiceKey.TRUSTSTORE_PWD);
						
			service.init(adapterName, 
					useMtls, mtlsInfo,
					maxTotalConnections, maxHostConnections);			
		
			if (service != null) {
				adapters.put(adapterName, service);
				adapterClass.put(adapterName, className);
			}
		} catch (Exception e) {
			logger.error("Cannot create a HttpClientAdapterService. : {}, adatperName : {}", className, adapterName, e);
			throw e;
		}
		return service;
	}
	
	public static void removeFactory(String adapterName) {
		String className = null;
		if (adapters.containsKey(adapterName)) {
			adapters.remove(adapterName);
			className = adapterClass.remove(adapterName);
			if(logger.isWarn()) {
				logger.warn("Remove HttpClientAdapterService. : {}, adatperName : {}", className, adapterName);
			}
		}
	}
}
