package com.eactive.eai.adapter.socket2;

import java.util.Properties;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.mina.common.IoSession;

import com.eactive.eai.adapter.ElinkDefaultAdapter;
import com.eactive.eai.adapter.Keys;
import com.eactive.eai.adapter.http.client.HttpClientAdapterServiceKey;
import com.eactive.eai.adapter.socket2.config.SocketAdapterManager;
import com.eactive.eai.adapter.socket2.protocol.ISocketAdapter;
import com.eactive.eai.common.util.Logger;
import com.eactive.eai.inbound.processor.GWSessionManager;

/** 
* 1. 기능 : Outbound Socket Adapter를 Access하기 위한 Java Class로 SocketControl에서 사용함.
* 2. 처리 개요 : 
* *     - OutboundControl Object를 통해 Outbound Socket을 통해 수동시스템과 Socket인터페이스를 위한
*         SocketAdapter Class
* 3. 주의사항 
*       - Outbound Process에서 Outbound Socket의 Adapter Group Name에 대한 Property를 지정해야한다.
* @author  : 
* @version : v 1.0.0
* @see : 관련 기능을 참조
* @since   : 
*/
public class SocketAdapterFacade extends ElinkDefaultAdapter
{ 
	static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
	static SocketAdapterFacade    socketAdapter = new SocketAdapterFacade();
    
    private SocketAdapterFacade() {
    }
    
    public static SocketAdapterFacade getInstance()
	{
		return socketAdapter;
    }
    
    /** 
    * 1. 기능 : SocketAdapter의 실행 Method
    * 2. 처리 개요 : 
    *     - OutboundControl Object를 생성 후 요청된 메시지를 Assign한 후 CallService를 통해
    *       해당 Outbound Adapter Group의 Socket Connection을 얻은 후 메시지 송수신에 따른 결과를
    *       리턴한다.
    * 3. 주의사항 
    *
    * @param    prop WLI OutboundAdapter의 Property정보, SocketAdapter의 경우 ADAPTER_GROUP_NAME
    *                Property Key에 Adapter Group Name을 지정한다.
    * @param    message Outbound process에서 요청하는 메시지 Object로 byte[] 속성의 메시지여야한다.               
    * @return   결과메시지 Object로 SYNC 유형의 경우 byte[] 메시지가 리턴된다.
    * @exception Exception
    **/  
    @Override
    public Object execute(Properties prop, Object message, Properties tempProp) throws Exception {
        String adapterGroupName = tempProp.getProperty(Keys.OUT_ADAPTER_GROUP_NAME);
        String adapterName = tempProp.getProperty(Keys.OUT_ADAPTER_NAME);
        if (logger.isDebug()) 
        	logger.debug("[SocketAdapterFacade] | Outbound Adapter Group is " + adapterGroupName);
        
        byte[] request = null;
        if ( message instanceof byte[]) {
            request = (byte[]) message;
        } else {
            throw new Exception(adapterGroupName + " | [SocketAdapterFacade] cannot send object type : " + message.getClass().getName());   
        }               

        ISocketAdapter adapter = null;
        
        if(adapterGroupName != null) adapter = SocketAdapterManager.getInstance().getOutboundSocketAdapter(adapterGroupName, adapterName);
        
        if (adapter == null)
        	throw new Exception(adapterGroupName + " | [SocketAdapterFacade] 수동 어댑터 정보 없음 adapterGroupName="+adapterGroupName +", adapterName="+adapterName);
        
        byte[] response = null;
        if (adapter.getContext().isSync()){
        	/**
        	 * adapter.getContext().getTimeout() 는 초단위
        	 * Process.INTERFACE_TIME_OUT 는 ms 단위
        	 * 초단위로 바꾸는 작업필요
        	 * TODO 전체적인 타임아웃값 확인필요
        	 */
        	int responseTimeout = 0;
        	String interfaceTimeout = tempProp.getProperty("INTERFACE_TIME_OUT");
        	if (interfaceTimeout == null || NumberUtils.toInt(interfaceTimeout) == 0){
        		responseTimeout = adapter.getContext().getTimeout();
        	}else{
        		try{
        			responseTimeout = Integer.parseInt(interfaceTimeout) / 1000;//ms 단위이기 때문에
        		}catch(Exception e){
        			responseTimeout = adapter.getContext().getTimeout();
        		}
        	}
        	if (responseTimeout == adapter.getContext().getTimeout()){
        		response = (byte[]) adapter.sendMessage(request );
        	}else{
        		response = (byte[]) adapter.sendMessage(request, responseTimeout );
        	}
        }else{
        	String sessionId = tempProp.getProperty(HttpClientAdapterServiceKey.TRANSACTION_ID);
        	logger.debug("[SocketAdapterFacade] | sessionId: {}", sessionId);
        	if (StringUtils.isNotBlank(sessionId)) {
        		IoSession session = GWSessionManager.getInstance().getSession(sessionId);
        		response = (byte[]) adapter.sendMessage(session, request);
        		GWSessionManager.getInstance().sessionOut(sessionId);
        	} else {
            	response = (byte[]) adapter.sendMessage(request);
        	}
        }
        
        
        return response;
    }    
} 
