package com.eactive.eai.common.routing;

import java.util.Arrays;
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.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.util.ApplicationContextProvider;
import com.eactive.eai.common.util.Logger;

@Component
public class RoutingManager implements Lifecycle {
	static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
	private Map<String, RoutingVO> routings;

	private boolean started;

	@Autowired
	private RoutingDAO routingDAO;

	private LifecycleSupport lifecycle = new LifecycleSupport(this);

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

	public void start() throws LifecycleException {
		if (started) {
			throw new LifecycleException("RECEAICRT201");
		}
		lifecycle.fireLifecycleEvent(STARTING_EVENT, this);
		try {
			init();
		} catch (Exception e) {
			throw new LifecycleException(ExceptionUtil.getErrorCode(e, "RECEAICRT202"));
		}
		started = true;
		lifecycle.fireLifecycleEvent(STARTED_EVENT, this);
	}

	private void init() throws Exception {
		this.routings = routingDAO.getAllRoutings();
	}

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

	public synchronized void reload(String routingName) throws Exception {
		RoutingVO vo = routingDAO.getRouting(routingName);
		if (vo != null) {
			this.routings.put(routingName, vo);
		} else {
			throw new Exception("Routing not found in Database : key[" + routingName + "]");
		}
	}

	public void stop() throws LifecycleException {
		if (!started) {
			throw new LifecycleException("RECEAICRT203");
		}
		lifecycle.fireLifecycleEvent(STOPING_EVENT, this);
		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 RoutingVO getRoutingVO(String name) {
		return (RoutingVO) routings.get(name);
	}

	public String[] getAllRoutingNames() {
		Iterator<String> it = this.routings.keySet().iterator();
		String[] routingNames = new String[this.routings.size()];
		for (int i = 0; it.hasNext(); i++) {
			routingNames[i] = it.next();
		}
		Arrays.sort(routingNames);
		return routingNames;
	}

	public Iterator<RoutingVO> getAllRoutingVOs() {
		return this.routings.values().iterator();
	}

	public void setRoutingVO(RoutingVO vo) {
		routings.put(vo.getName(), vo);
	}

	public void removeRoutingVO(String name) {
		routings.remove(name);
	}
}
