package com.eactive.eai.common.b2badaptermapping;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.eactive.eai.common.dao.DAOException;
import com.eactive.eai.common.exception.ExceptionUtil;
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.lifecycle.LifecycleSupport;
import com.eactive.eai.common.server.EAIServerManager;
import com.eactive.eai.common.util.ApplicationContextProvider;
import com.eactive.eai.common.util.Logger;

@Component
public class B2BAdapterMapManager implements Lifecycle {

	static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
	private boolean started;

	private Map<String, B2BAdapterMapVO> messages = new HashMap<>();

	private LifecycleSupport lifecycle = new LifecycleSupport(this);

	@Autowired
	private B2BAdapterMapDAO b2bAdapterMapDAO;

	public static B2BAdapterMapManager getInstance() {
		return ApplicationContextProvider.getContext().getBean(B2BAdapterMapManager.class);
	}

	public void start() throws LifecycleException {
		if (started)
			throw new LifecycleException("RECEAICBA201");

		lifecycle.fireLifecycleEvent(STARTING_EVENT, this);

		try {
			init();
		} catch (Exception e) {
			throw new LifecycleException(ExceptionUtil.getErrorCode(e, "RECEAICBA202"));
		}

		started = true;

		lifecycle.fireLifecycleEvent(STARTED_EVENT, this);
	}

	public void init() throws DAOException {
		String eaiInstCd = EAIServerManager.getInstance().getLocalServerName();
		messages = b2bAdapterMapDAO.getAllB2BAdapterMaps(eaiInstCd);
	}

	public synchronized void reload() throws Exception {
		if (logger.isWarn()) {
			logger.warn("B2BAdapterMapManager] reload all Started ...");
		}
		init();
		if (logger.isWarn()) {
			logger.warn("B2BAdapterMapManager] reload all finished ...");
		}
	}

	public synchronized void reload(String eaiSvcCd) throws Exception {
		if (logger.isWarn()) {
			logger.warn("B2BExtractManager] reload Started ...");
		}
		Map<String, B2BAdapterMapVO> map = b2bAdapterMapDAO
				.getB2BAdapterMap(EAIServerManager.getInstance().getLocalServerName(), eaiSvcCd);

		if (map != null) {
			Iterator<String> it = map.keySet().iterator();
			String key = "";
			while (it.hasNext()) {
				key = (String) it.next();
				messages.put(key, map.get(key));
			}
		}

		if (logger.isWarn()) {
			logger.warn("B2BExtractManager] reload finished ...");
		}
	}

	public synchronized void remove(String eaiSvcCd) throws Exception {
		if (logger.isWarn()) {
			logger.warn("B2BExtractManager] remove Started ...");
		}
		messages.remove(eaiSvcCd);
		if (logger.isWarn()) {
			logger.warn("B2BExtractManager] remove finished ...");
		}
	}

	public void stop() throws LifecycleException {

		if (!started)
			throw new LifecycleException("RECEAICBA203");

		// Notify our interested LifecycleListeners
		lifecycle.fireLifecycleEvent(STOPING_EVENT, this);

		messages.clear();

		started = false;
		// Notify our interested LifecycleListeners
		lifecycle.fireLifecycleEvent(STOPPED_EVENT, this);
	}

	public void addLifecycleListener(LifecycleListener listener) {
		lifecycle.addLifecycleListener(listener);
	}

	public LifecycleListener[] findLifecycleListeners() {
		return lifecycle.findLifecycleListeners();
	}

	public void removeLifecycleListener(LifecycleListener listener) {
		lifecycle.removeLifecycleListener(listener);
	}

	public boolean isStarted() {
		return this.started;
	}

	public B2BAdapterMapVO getB2BAdapterMap(String eaiSvcCd) {
		return messages.get(eaiSvcCd);
	}

	public void setB2BAdapterMap(String eaiSvcCd, B2BAdapterMapVO msg) {
		String currentInstCd = EAIServerManager.getInstance().getLocalServerName();

		if (currentInstCd != null && currentInstCd.equals(msg.getEaiInstCd())) {
			B2BAdapterMapVO current = messages.get(eaiSvcCd);

			if (current == null) {
				messages.put(eaiSvcCd, msg);
			} else {
				String[] keys = msg.getAllKeyNames();
				for (int i = 0; i < keys.length; i++) {
					B2BAdapterMapFldVO fvo = msg.getB2BAdapterMapFld(keys[i]);
					if (fvo == null)
						continue;
					current.addB2BAdapterMapFld(fvo.getB2bExtnlInstiCd(), fvo.getBzwkVal(), fvo.getAdapterGroupName(),
							fvo.getAdapterName());
				}
			}
		}
	}

	public void updateB2BAdapterMap(String eaiSvcCd, B2BAdapterMapVO msg) {
		String currentInstCd = EAIServerManager.getInstance().getLocalServerName();
		if (currentInstCd != null && currentInstCd.equals(msg.getEaiInstCd())) {
			B2BAdapterMapVO current = messages.get(eaiSvcCd);
			if (current == null) {
				messages.put(eaiSvcCd, msg);
			} else {
				String[] keys = msg.getAllKeyNames();
				for (int i = 0; i < keys.length; i++) {
					B2BAdapterMapFldVO fvo = msg.getB2BAdapterMapFld(keys[i]);
					if (fvo == null) {
						continue;
					}
					current.addB2BAdapterMapFld(fvo.getB2bExtnlInstiCd(), fvo.getBzwkVal(), fvo.getAdapterGroupName(),
							fvo.getAdapterName());
				}
			}
		}
	}

	public void removeB2BAdapterMap(String eaiSvcCd) {
		messages.remove(eaiSvcCd);
	}

	public void removeB2BAdapterMap(String eaiSvcCd, B2BAdapterMapVO msg) {
		String currentInstCd = EAIServerManager.getInstance().getLocalServerName();
		if (currentInstCd != null && currentInstCd.equals(msg.getEaiInstCd())) {
			B2BAdapterMapVO current = messages.get(eaiSvcCd);
			if (current != null) {
				String[] keys = msg.getAllKeyNames();
				for (int i = 0; i < keys.length; i++) {
					B2BAdapterMapFldVO fvo = msg.getB2BAdapterMapFld(keys[i]);
					if (fvo == null) {
						logger.warn("B2BAdapterMapFldVO is null key=" + keys[i]);
						continue;
					}
					current.deleteB2BAdapterMapFld(fvo.getB2bExtnlInstiCd(), fvo.getBzwkVal());
				}

				if (current.getB2BAdapterMapFldLength() == 0) {
					messages.remove(eaiSvcCd);
				}
			}
		}
	}

	public String[] getAllKeyNames() {
		Set<String> keySet = this.messages.keySet();
		String[] name = keySet.toArray(new String[keySet.size()]);
		Arrays.sort(name);
		return name;
	}
}
