package com.eactive.eai.common.messagekey;

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

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

import com.eactive.eai.common.dao.DAOException;
import com.eactive.eai.common.dao.DAOFactory;
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.routing.RoutingDAO;
import com.eactive.eai.common.util.ApplicationContextProvider;
import com.eactive.eai.common.util.Logger;

@Component
public class MessageKeyManager implements Lifecycle {
	private static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);

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

	private LifecycleSupport lifecycle = new LifecycleSupport(this);

	private boolean started;

	@Autowired
	private MessageKeyDAO messageKeyDAO;

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

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

		lifecycle.fireLifecycleEvent(STARTING_EVENT, this);

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

		started = true;
		lifecycle.fireLifecycleEvent(STARTED_EVENT, this);
	}

	private void init() throws Exception {
		messages = null;
		messages = messageKeyDAO.getAllMessageKeys();
	}

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

	public MessageKeyVO getMessageKey(String adptrBzwkGroupName, String ioDstcd) throws DAOException {
		return messageKeyDAO.getMessageKey(adptrBzwkGroupName, ioDstcd);
	}

	public synchronized void reload(String adptrBzwkGroupName, String ioDstcd) throws Exception {
		if (logger.isWarn()) {
			logger.warn("MessageKeyManager] reload part : " + adptrBzwkGroupName + "," + ioDstcd + " Started ...");
		}

		if (adptrBzwkGroupName != null && ioDstcd != null) {
			MessageKeyVO vo = getMessageKey(adptrBzwkGroupName, ioDstcd);
			messages.put(vo.getName(), vo);
		} else {
			throw new Exception("keyName format error " + adptrBzwkGroupName + "," + ioDstcd);
		}
		if (logger.isWarn()) {
			logger.warn("MessageKeyManager] reload " + adptrBzwkGroupName + "," + ioDstcd + " finished ...");
		}
	}

	/**
	 * 어댑터 CM 반영할때 쓰이는 용도
	 */
	public synchronized void reload(String adptrBzwkGroupName) throws Exception {
		if (logger.isWarn()) {
			logger.warn("MessageKeyManager] reload " + adptrBzwkGroupName + " Started ...");
		}

		if (adptrBzwkGroupName != null) {
			MessageKeyVO vo = getMessageKey(adptrBzwkGroupName, "I");
			if (vo != null) {
				messages.put(vo.getName(), vo);
			}
			vo = getMessageKey(adptrBzwkGroupName, "O");
			if (vo != null) {
				messages.put(vo.getName(), vo);
			}
		} else {
			throw new Exception("keyName format error " + adptrBzwkGroupName);
		}
		if (logger.isWarn()) {
			logger.warn("MessageKeyManager] reload " + adptrBzwkGroupName + " finished ...");
		}
	}

	public void stop() throws LifecycleException {
		if (!started)
			throw new LifecycleException("RECEAICMK203");

		lifecycle.fireLifecycleEvent(STOPING_EVENT, this);

		messages.clear();

		started = false;
		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 MessageKeyVO getMessageKey(String code) {
		return messages.get(code);
	}

	public void setMessageKey(String code, MessageKeyVO msg) {
		messages.put(code, msg);
	}

	public void updateMessageKey(String code, MessageKeyVO msg) {
		messages.put(code, msg);
	}

	public void removeMessageKey(String code) {
		messages.remove(code);
	}

	public String[] getAllKeyNames() {
		String[] names = this.messages.keySet().toArray(new String[0]);
		Arrays.sort(names);
		return names;
	}
}
