package com.eactive.eai.agent.adapter;

import java.util.Iterator;
import java.util.Vector;

import org.apache.commons.lang3.StringUtils;

import com.eactive.eai.adapter.AdapterGroupVO;
import com.eactive.eai.adapter.AdapterManager;
import com.eactive.eai.adapter.AdapterVO;
import com.eactive.eai.adapter.Keys;
import com.eactive.eai.adapter.http.dynamic.HttpDynamicInAdapterManager;
import com.eactive.eai.adapter.http.healthcheck.HttpTargetMonitorManager;
import com.eactive.eai.agent.command.Command;
import com.eactive.eai.agent.command.CommandException;
import com.eactive.eai.common.server.EAIServerManager;
import com.eactive.eai.common.util.Logger;

public class ReloadAdapterGroupCommand extends Command {
	private static final long serialVersionUID = 1L;

	private static Object obj = new Object();

	public ReloadAdapterGroupCommand() {
		super("ReloadAdapterGroupCommand");
	}

	/** 
	    * 1. 기능 :  AdapterManager에 AdapterGroupVO를 제거
	    * 2. 처리 개요 : AdapterGroupVO의 EAISvrInstNm이 DEFAULT_SERVER(ALL) 이거나  LocalServer인 경우
	    *           AdapterManager에 등록된 해당 AdapterGroupVO를 제거
	    * 3. 주의사항 : 테스트용임
	    *
	    * @exception    CommandException	Argument Type이 다르거나 Command 수행중 Exception이 발생할 경우
	    **/
	public Object execute() throws CommandException {
		Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
		if (logger.isInfo())
			logger.info(this.name + " is executed");

		if (!(args instanceof String)) {
			String rspErrorCode = "RECEAIMCM001";
			String msg = makeException(rspErrorCode, null);
			if (logger.isError())
				logger.error(msg);
			throw new CommandException(msg);
		}

		AdapterManager manager = AdapterManager.getInstance();

		String adapterGroupName = (String) args;
		// Stop & Remove Adapter Group
		synchronized (obj) {
			try {
				AdapterGroupVO gvo = manager.getAdapterGroupVO(adapterGroupName);

				if (gvo != null) {
					try {
						gvo.stop();
						if (logger.isInfo())
							logger.info("AdapterGroupVO[" + adapterGroupName + "] stop()");
					} catch (Exception e) {
						if (logger.isInfo())
							logger.info("AdapterGroupVO[" + adapterGroupName + "] not started status- skip stop()");
						// if Error continue...
					}

					manager.removeAdapterGroupVO(adapterGroupName);
				}
			} catch (Exception e) {
				String rspErrorCode = "RECEAIMCM002";
				String msg = makeException(rspErrorCode, e);
				if (logger.isError())
					logger.error(msg, e);
				throw new CommandException(msg);
			}

			// Load from DB and Start
			AdapterGroupVO reloadGroupVO = null;
			try {
				reloadGroupVO = manager.loadAdapterGroup(adapterGroupName);
			} catch (Exception e) {
				String rspErrorCode = "RECEAIMCM002";
				String msg = makeException(rspErrorCode, e);
				if (logger.isError())
					logger.error(msg, e);
				throw new CommandException(msg);
			}

			Vector<String> vt = new Vector<>();

			String localServerName = EAIServerManager.getInstance().getLocalServerName();
			for (Iterator<AdapterVO> it = reloadGroupVO.getAdapters(); it.hasNext();) {
				AdapterVO avo = it.next();
				if (!com.eactive.eai.common.server.Keys.DEFAULT_SERVER.equals(avo.getEaiSevrInstncName())
						&& !localServerName.equals(avo.getEaiSevrInstncName())) {
					vt.add(avo.getName());
				}
			}
			for (int i = 0; i < vt.size(); i++) {
				reloadGroupVO.removeAdapterVO(vt.get(i));
			}

			if (reloadGroupVO != null) {
				try {
					if (logger.isWarn())
						logger.warn("ReloadAdapterGroupCommand] execute. - UsedFlag = " + reloadGroupVO.isUsedFlag());
					if (reloadGroupVO.isUsedFlag()) {
						// WCA 어댑터에서 start시 어댑터를 조회하므로 순서를 변경한다.
						manager.addAdapterGroupVO(reloadGroupVO);
						reloadGroupVO.start();
					} else {
						if (logger.isDebug())
							logger.debug("AddAdapterGroupCommand] execute. - UsedFlag = " + reloadGroupVO.isUsedFlag());
					}
				} catch (Exception e) {
					String rspErrorCode = "RECEAIMCM002";
					String msg = makeException(rspErrorCode, e);
					if (logger.isError())
						logger.error(msg, e);
					throw new CommandException(msg);

				}
			} else {
				if (logger.isWarn()) {
					logger.warn("ReloadAdapterGroupCommand] execute. - vo is null");
				}
			}
			
			// HTTP, REST inbound Adapter PathMap reload
			try {
				reloadHttpPathMap(reloadGroupVO);
			} catch (Exception e) {
				String rspErrorCode = "RECEAIMCM002";
				String msg = makeException(rspErrorCode, e);
				if (logger.isError())
					logger.error(msg, e);
				throw new CommandException(msg);
			}
			
			// HTTP, REST outbound adapter HealthCheck
			try {
				reloadHttpHealthChecker(reloadGroupVO);
			} catch (Exception e) {
				String rspErrorCode = "RECEAIMCM002";
				String msg = makeException(rspErrorCode, e);
				if (logger.isError())
					logger.error(msg, e);
				throw new CommandException(msg);
			}
		}

		return "success";
	}

	private void reloadHttpPathMap(AdapterGroupVO reloadGroupVO) throws Exception {
		if (reloadGroupVO != null
				&& (StringUtils.equals(reloadGroupVO.getType(), Keys.TYPE_HTTP)
						|| StringUtils.equals(reloadGroupVO.getType(), Keys.TYPE_REST))
				&& StringUtils.equals(reloadGroupVO.getGubun(), "I")) {
			HttpDynamicInAdapterManager manager = HttpDynamicInAdapterManager.getInstance();
			manager.reloadAdapterUrl(reloadGroupVO);
		}
	}
	
	private void reloadHttpHealthChecker(AdapterGroupVO reloadGroupVO) {
		Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
		HttpTargetMonitorManager manager = HttpTargetMonitorManager.getInstance();
		if(manager == null || !manager.isStarted()) {
			logger.info("HttpTargetMonitorManager not used or not started!");
			return;
		}
		
		if (reloadGroupVO != null
			&& (StringUtils.equals(reloadGroupVO.getType(), Keys.TYPE_HTTP)
					|| StringUtils.equals(reloadGroupVO.getType(), Keys.TYPE_REST))
			&& StringUtils.equals(reloadGroupVO.getGubun(), Keys.ADAPTER_OUT)) {
			manager.addAdapterGroup(reloadGroupVO);			
		}
		else {
			if(logger.isInfo()) {
				String adapterGroupName = (reloadGroupVO == null ? "" : reloadGroupVO.getName());
				logger.info("Not suitable for HttpTargetMonitorManager - " +  adapterGroupName );
			}
		}
	}
}
