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

import com.eactive.eai.adapter.*;
import com.eactive.eai.agent.command.CommandException;
import com.eactive.eai.common.lifecycle.Lifecycle;
import com.eactive.eai.common.lifecycle.LifecycleException;
import com.eactive.eai.common.lifecycle.LifecycleListener;
import com.eactive.eai.common.util.CamelCaseUtil;
import com.eactive.eai.common.util.Logger;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

public class HttpDynamicInAdapterManager implements Lifecycle {

	public static String HTTP_PARAM_TYPE = "HTTP_TYPE";
	public static String API_PATH = "API_PATH";
	
	Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
	
    private static HttpDynamicInAdapterManager instance = new HttpDynamicInAdapterManager();
    
	//private ConcurrentHashMap<String, HttpDynamicInAdapterUri> adptUriMap = new ConcurrentHashMap<String, HttpDynamicInAdapterUri>();
    public ConcurrentHashMap<String, HttpDynamicInAdapterUri> adptUriMap = new ConcurrentHashMap<String, HttpDynamicInAdapterUri>();

    
    public static HttpDynamicInAdapterManager getInstance() {
        return instance;   
    }
    
	public HttpDynamicInAdapterUri getAdptUri(String uri) {
		return adptUriMap.get( uri );
	}

	public void removeAdptUri(AdapterVO avo) {
		try {
			AdapterGroupVO gvo = avo.getAdapterGroupVO();
	    	if ( gvo.getType().equals(Keys.TYPE_HTTP) && gvo.getGubun().equals("I") ) {
	    		removeAdptUri(avo.getAdapterGroupName(), avo.getName());
	    	}
		} catch (Exception e) {
			logger.error("HttpDynamicInAdapterManager] dynamic HTTP adpater remove error." + avo.toString(), e);
		}
	}

	public void removeAdptUri(String adptGrpName, String adptName) {
		for( HttpDynamicInAdapterUri adptUri : adptUriMap.values() ) {
			if ( adptUri.isEqualsAdpt(adptGrpName, adptName) ) {
				adptUriMap.remove( adptUri.getUri() );
				if ( logger.isDebug() ) {
					logger.debug("HttpDynamicInAdapterManager] remove " + adptGrpName + "-" + adptName );
				}
				
				break;
			}
		}
	}

	public void setDynamicUrl(AdapterVO avo) throws Exception {
		try {
	        AdapterGroupVO gvo = avo.getAdapterGroupVO();
	        
	        if(gvo == null){
	        	removeAdptUriMapByAdapterGroupName(avo.getAdapterGroupName());
	        }
	        else if ( gvo.getType().equals(Keys.TYPE_HTTP) && gvo.getGubun().equals("I") ) {
	    		AdapterPropManager manager = AdapterPropManager.getInstance();        
	            Properties httpProp  = manager.getProperties(avo.getPropGroupName());
	            String httpType = httpProp.getProperty(HTTP_PARAM_TYPE,"STANDARD");
	            String httpUrl = "/HTT/"+CamelCaseUtil.converCamelCaseWithBrace(avo.getAdapterGroupName(),"_"); 
            	adptUriMap.put( httpUrl, new HttpDynamicInAdapterUri(avo.getAdapterGroupName(), avo.getName(), httpUrl, httpType));
				if ( logger.isDebug() ) {
					logger.debug("HttpDynamicInAdapterManager] set " + avo.getAdapterGroupName() + "-" + avo.getName() + ", uri:" + httpUrl );
				}	            	
			} else if (gvo.getType().equals(Keys.TYPE_REST) && gvo.getGubun().equals("I")) {
				AdapterPropManager manager = AdapterPropManager.getInstance();
				Properties httpProp = manager.getProperties(avo.getPropGroupName());
				String httpType = httpProp.getProperty(HTTP_PARAM_TYPE, "REST");
				String httpUrl = httpProp.getProperty(API_PATH);
				httpUrl = StringUtils.removeEnd(httpUrl, "/");
				if (StringUtils.isNotBlank(httpUrl)) {
					// /api/vi/public
					if (!StringUtils.startsWith(httpUrl, "/")) {
						httpUrl = "/" + httpUrl;
					}

					// 1. URL이 이미 있는데, 그 URL이 다른 어댑터에 이미 설정되어 있다면 오류처리(기존 어댑터 보호)
					HttpDynamicInAdapterUri adapterUri = adptUriMap.get(httpUrl);
					
					logger.debug("#### setDynamicUrl:"+adptUriMap.toString());
					
					if (adapterUri != null
							&& !StringUtils.equals(avo.getAdapterGroupName(), adapterUri.getAdptGrpName())) {
						throw new CommandException("The URI is already in use by another adapter, "+adapterUri.getAdptGrpName());
					}

					// 2. 어댑터 기준 기존 데이터 삭제
					removeAdptUriMapByAdapterGroupName(avo.getAdapterGroupName());

					// 3. 새로 추가
					adptUriMap.put(httpUrl,
							new HttpDynamicInAdapterUri(avo.getAdapterGroupName(), avo.getName(), httpUrl, httpType));
					if (logger.isDebug()) {
						logger.debug("HttpDynamicInAdapterManager] set " + avo.getAdapterGroupName() + "-"
								+ avo.getName() + ", uri:" + httpUrl);
						logger.debug("HttpDynamicInAdapterManager] adptUriMap " + adptUriMap.toString());
					}
				}
			}
		} catch (CommandException e) {
			throw new Exception(e.getMessage());
		} catch (Exception e) {
			logger.error("HttpDynamicInAdapterManager] dynamic HTTP adapter add error." + avo.toString(), e);			
		}
	}

	public void removeAdptUriMapByAdapterGroupName(String adapterGroupName) throws Exception {
		for (HttpDynamicInAdapterUri adptUri : adptUriMap.values()) {
			if (StringUtils.equals(adptUri.getAdptGrpName(), adapterGroupName)) {
				adptUriMap.remove(adptUri.getUri());
				if (logger.isDebug()) {
					logger.debug("HttpDynamicInAdapterManager] remove " + adptUri.toString() + " for "+adapterGroupName);
				}

				break;
			}
		}
	}

	@Override
	public void addLifecycleListener(LifecycleListener listener) {
		
		
	}

	@Override
	public LifecycleListener[] findLifecycleListeners() {
		
		return null;
	}

	@Override
	public void removeLifecycleListener(LifecycleListener listener) {
		
		
	}

	@Override
	public void start() throws LifecycleException {
		
		AdapterManager adptManager = AdapterManager.getInstance();
		HashMap adptGrps = null;
        
		try {
			adptGrps = adptManager.getAllAdapterGroupVO();
					
	        for(Object obj : adptGrps.values()) {
	        	AdapterGroupVO gvo = (AdapterGroupVO)obj;
	        	if(logger.isDebug()){
	        		logger.debug("adpter : "+gvo.getName()+"-->"+gvo.toString());
	        	}
				if ((gvo.getType().equals(Keys.TYPE_HTTP) || gvo.getType().equals(Keys.TYPE_REST))
						&& gvo.getGubun().equals("I")) {
		            ArrayList<AdapterVO> adpts = null;
	                Iterator i = gvo.getAdapters();
	                
	                while ( i.hasNext() ) {
	                	AdapterVO avo = (AdapterVO)i.next();
	                	setDynamicUrl( avo );
	                }
	        	}
	        }
		} catch (Exception e) {
			logger.error("HttpDynamicInAdapterManager] start error", e);			
		}		
	}

	@Override
	public void stop() throws LifecycleException {
		
	}

	@Override
	public boolean isStarted() {
		
		return false;
	}

	@SuppressWarnings("rawtypes")
	public void reloadAdapterUrl(AdapterGroupVO reloadGroupVO) throws Exception {
		Iterator i = reloadGroupVO.getAdapters();
		while (i.hasNext()) {
			AdapterVO avo = (AdapterVO) i.next();
			setDynamicUrl(avo);
		}
	}
}
