package com.eactive.eai.adapter;

import java.io.Serializable;

import org.apache.commons.lang3.StringUtils;

import com.eactive.eai.adapter.listener.AdapterException;
import com.eactive.eai.adapter.listener.AdapterListener;
import com.eactive.eai.adapter.listener.ListenerUtil;
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.testcall.TestCallManager;
import com.eactive.eai.common.util.Logger;

public class AdapterVO implements Serializable, Lifecycle {
	static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);

	private AdapterGroupVO adapterGroupVO; // 어댑터 그룹

	private String adapterGroupName; // 어뎁터업무그룹명[TSEAIAD02.AdptrBzwkGroupName]
	private String name; // 어뎁터업무명[TSEAIAD02.AdptrBzwkName]
	private String eaiSevrInstncName; // 서버인스탄스명[TSEAIAD02.EAISevrInstncName] - migration added.
	private String listenerClass; // 리스너클래스명[TSEAIAD02.LstnerClsName]
	private String testCallClass; // 테스터클래스명[TSEAIAD02.TestClsName]
	private String propGroupName; // 프라퍼티그룹명[TSEAIAD02.PrptyGroupName]
	private String description; // 어댑터설명[TSEAIAD02.AdptrDesc]
	private String propGroupDesc; // 프라퍼티그룹설명

	private boolean status;
	private transient AdapterListener adapterListener;
	private boolean started;
	private LifecycleSupport lifecycle = new LifecycleSupport(this);
	
	private int requestCount;
	private int weight;
	
    public int getWeight() {
		return weight;
	}

	public void setWeight(int weight) {
		this.weight = weight;
	}

	public int getRequestCount() {
        return requestCount;
    }

    public synchronized void incrementRequestCount() {
        requestCount++;
    }
    
    public synchronized void decrementRequestCount() {
        requestCount--;
    }
    
	public AdapterVO() {
		this.requestCount = 0;
		this.weight = 1;
	}

	public AdapterVO(String name) {
		this.name = name;
		this.requestCount = 0;
		this.weight = 1;
	}

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

	public void setAdapterGroupName(String adapterGroupName) {
		this.adapterGroupName = adapterGroupName;
	}

	public String getAdapterGroupName() {
		return this.adapterGroupName;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getName() {
		return this.name;
	}

	public void setListenerClass(String listenerClass) {
		this.listenerClass = listenerClass;
	}

	public String getListenerClass() {
		return this.listenerClass;
	}

	public void setTestCallClass(String testCallClass) {
		this.testCallClass = testCallClass;
	}

	public String getTestCallClass() {
		return this.testCallClass;
	}

	public void setPropGroupName(String propGroupName) {
		this.propGroupName = propGroupName;
	}

	public String getPropGroupName() {
		return this.propGroupName;
	}

	public void setAdapterGroupVO(AdapterGroupVO group) {
		this.adapterGroupVO = group;
	}

	public AdapterGroupVO getAdapterGroupVO() {
		return this.adapterGroupVO;
	}

	private void setStatus(boolean status, boolean checkTestCall) {
		this.status = status;
		
		if (checkTestCall && !this.status && this.testCallClass != null && !this.testCallClass.equals("")) {
			TestCallManager tmanager = TestCallManager.getInstance();
			try {
				tmanager.addTester(this);

				String[] msgArgs = new String[1];
				msgArgs[0] = this.toString();
				if (logger.isInfo())
					logger.info(ExceptionUtil.make("RICEAIAAC034", msgArgs));
			} catch (Exception e) {
				throw new RuntimeException(ExceptionUtil.getErrorCode(e, "RICEAIAAC035"), e);
			}
		}

		if (this.status) {
			this.adapterGroupVO.active(this);
		} else {
			this.adapterGroupVO.disable(this);
		}
	}
	
	public synchronized void setStatus(boolean status) {
		setStatus(status, true);
	}
	
	public synchronized void setStatusForcely(boolean status) {
		setStatus(status, false);
	}
	
	public synchronized boolean isStatus() {
		return this.status;
	}

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

		lifecycle.fireLifecycleEvent(STARTING_EVENT, this);
		
		if (StringUtils.isEmpty(listenerClass)) {
			listenerClass = ListenerUtil.getDefaultListenerClass(adapterGroupVO.getType(), adapterGroupVO.getGubun());
			if(logger.isWarn() && StringUtils.isNotEmpty(listenerClass)) {
				logger.warn("Use DefaultListenerClass {} - {}",adapterGroupVO.getName(), listenerClass);
			}
		}
		
		if (StringUtils.isNotEmpty(listenerClass)) {
			try {
				adapterListener = (AdapterListener) Class.forName(listenerClass).newInstance();
				adapterListener.setAdapterInfo(this);
				adapterListener.start();
			} catch (Exception e) {
				throw new LifecycleException(ExceptionUtil.getErrorCode(e, "RECEAIAAC037"), e);
			}
		}

		started = true;
		// SocketAdapter 기동시에 설정하므로
		// socket2일 때는 status 를 setting 하지 않음.
		if (adapterListener == null) {
			status = true;
			this.adapterGroupVO.active(this);
		} else {
			if (!(adapterListener instanceof com.eactive.eai.adapter.socket2.SocketAdapterListener)) {
				status = true;
			} else {
				this.adapterGroupVO.active(this);
			}
		}
		lifecycle.fireLifecycleEvent(STARTED_EVENT, this);
		if(logger.isWarn()) {
			logger.warn("Adapter started {} {} - {}",adapterGroupVO.getName(), getName(), listenerClass);
		}
	}

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

		lifecycle.fireLifecycleEvent(STOPING_EVENT, this);

		try {
			if (adapterListener != null)
				adapterListener.stop();
		} catch (AdapterException e) {
			throw new LifecycleException(ExceptionUtil.getErrorCode(e, "RECEAIAAC039"), e);
		}

		started = false;
		status = false;
		this.adapterGroupVO.disable(this);
		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 void setDescription(String description) {
		this.description = description;
	}

	public String getDescription() {
		return this.description;
	}

	public String toString() {
		StringBuilder sb = new StringBuilder();
		sb.append("AdapterVO[ name=").append(name);
		sb.append(", adapterGroupName=").append(adapterGroupName);
		sb.append(", eaiSevrInstncName=").append(eaiSevrInstncName);
		sb.append(", listenerClass=").append(listenerClass);
		sb.append(", testCallClass=").append(testCallClass);
		sb.append(", propGroupName=").append(propGroupName);
		sb.append(", description=").append(description);
		sb.append(", status=").append(status);
		sb.append(", requestCount=").append(requestCount);
		sb.append(" ]");

		return sb.toString();
	}

	public void setEaiSevrInstncName(String eaiSevrInstncName) {
		this.eaiSevrInstncName = eaiSevrInstncName;
	}

	public String getEaiSevrInstncName() {
		return this.eaiSevrInstncName;
	}

	public void setPropGroupDesc(String propGroupDesc) {
		this.propGroupDesc = propGroupDesc;
	}

	public String getPropGroupDesc() {
		return this.propGroupDesc;
	}
}
