package com.eactive.eai.common.session; 

import java.util.concurrent.ConcurrentHashMap;

import org.apache.mina.common.IoSession;

import com.eactive.eai.adapter.socket2.common.ExpiringMap;
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.sessioninfo.SessionInfoVO;
import com.eactive.eai.common.util.DatetimeUtil;
import com.eactive.eai.common.util.Logger;

/** 
* 1. 기능 : websocket session 정보를 관리하는 Manager 클래스
* 2. 처리 개요 : ehcache 로 session 을 공유함.
* 3. 주의사항 
*
* @author  : 
* @version : v 1.0.0
* @see : 관련 기능을 참조
* @since   : 
*  : 
*/
public class TcpSessionManager implements Lifecycle
{ 
    /**
     * Default Logger
     */
    static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);

    /**
     * SessionManager Single Instance
     */    
    private static TcpSessionManager instance;
	/**
	 * cache 정보  
	 */
	  private static ExpiringMap<String,String> uidCache ;	//<sessionString, uid>
	  
	  private static ExpiringMap<String, IoSession> chnCache ;   //<uid, session>


    /**
     * 기동 여부
     */    
    private boolean started;

    /**
     * LifeccyleSupport object
     */    
    private LifecycleSupport lifecycle = new LifecycleSupport(this);
	
    /** 
    * 1. 기능 :  Default Constructor
    * 2. 처리 개요 : 라우팅 Rule 정보를 저장하기 위한 HashMap을 초기화한다.
    * 3. 주의사항 
    *
    **/
    private TcpSessionManager() {
    	//init();
    }
    
    /** 
    * 1. 기능 :  SessionManager Singleton Object를 반환하는 getter method
    * 2. 처리 개요 : SessionManager Singleton Object를 반환한다.
    * 3. 주의사항 
    *
    * @return   SessionManager Singleton object
    **/
    public static TcpSessionManager getInstance() {
        if(instance == null) {
            synchronized(TcpSessionManager.class) {
                if(instance==null) {
                    instance = new TcpSessionManager();   
                }   
            }
        }
        return instance;   
    }
    
    /** 
    * 1. 기능 :  Lifecycle의 start 메서드로 RoutingMangaer를 초기화하는 메서드
    * 2. 처리 개요 : RoutingDAO를 이용해 추출 Rule 정보 모두를 가져와 초기화한다.
    * 3. 주의사항 
    *
    * @exception    LifecycleException  이미 시작되었거나(RECEAICBM201), RoutingDAO를 통해 Rule 정보를 가져오다 DAOExcepiton이 발생될 경우(RECEAICRT201)
    * 
    **/
    public void start() throws LifecycleException {
        if (started)
            throw new LifecycleException("RECEAICRT201");
        
        
        // Notify our interested LifecycleListeners
        lifecycle.fireLifecycleEvent(STARTING_EVENT, this);
        

        this.uidCache = new ExpiringMap<String,String>(86400,600);
        this.chnCache = new ExpiringMap<String,IoSession>(86400,600);
//        this.uuidCache = new ExpiringMap<String,IoSession>(60,1);
//        this.chnCache = new ExpiringMap<String,IoSession>(60,1);
        
        started = true;
        // Notify our interested LifecycleListeners
        lifecycle.fireLifecycleEvent(STARTED_EVENT, this);
    }

    /** 
    * 1. 기능 :  Lifecycle의 stop 메서드로 SessionManager를 종료하는 메서드
    * 2. 처리 개요 : 멤버에 캐싱한 라우팅 Rule 정보를 clear한다.
    * 3. 주의사항 
    *
    * @exception    LifecycleException  이미 종료된 경우 발생(RECEAICRT203)
    **/
    public void stop() throws LifecycleException {
        // Validate and update our current component state
        if (!started)
            throw new LifecycleException("RECEAICRT203");
		
        // Notify our interested LifecycleListeners
        lifecycle.fireLifecycleEvent(STOPING_EVENT, this);
        
        
        
        
        started = false;
        // Notify our interested LifecycleListeners
        lifecycle.fireLifecycleEvent(STOPPED_EVENT, this);
    }
    
    /** 
    * 1. 기능 :  LifecycleListener를 등록하는 메서드
    * 2. 처리 개요 : LifecycleListener를 등록한다.
    * 3. 주의사항 
    *
    * @param    listener    LifecycleEvent를 수신한 LifecycleListener
    **/
    public void addLifecycleListener(LifecycleListener listener)
    {
        lifecycle.addLifecycleListener(listener);
    }

    /** 
    * 1. 기능 :  등록된 LifecycleListener 리스트를 반환하는 메서드
    * 2. 처리 개요 : 등록된 LifecycleListener 리스트를 반환하다.
    * 3. 주의사항 
    *
    * @return   등록된 LifecycleListener 리스트
    **/
    public LifecycleListener[] findLifecycleListeners()
    {
        return lifecycle.findLifecycleListeners();
    }

    /** 
    * 1. 기능 :  등록된 LifecycleListener를 삭제하는 메서드
    * 2. 처리 개요 : 파라미터의 LifecycleListener를 삭제한다.
    * 3. 주의사항 
    *
    * @param    listener    삭제할 LifecycleListener
    **/
    public void removeLifecycleListener(LifecycleListener listener)
    {
        lifecycle.removeLifecycleListener(listener);
    }
    
    /** 
    * 1. 기능 :  SessionManager의 초기화 여부를 반환하는 getter 메서드
    * 2. 처리 개요 : SessionManager의 초기화 여부를 반환한다.
    * 3. 주의사항 
    *
    * @return   초기화 여부
    **/
    public boolean isStarted() {
        return this.started;   
    }
    
    public ExpiringMap getSessionList(){
    	return chnCache;
    }
    public synchronized void sessionOpen(IoSession session){
    	logger.warn("TcpSessionManager ] session Opened - [ " + session + "]");
    }
    
//    public synchronized void sessionLogin(String uuid, String usrid, IoSession session){
//    	if(usrid == null && session == null){
//    		return;
//    	}
//    	this.uidCache.put(session.toString(), usrid);
//    	this.chnCache.put(usrid, session);
//    	
//    	logger.warn("TcpSessionManager ] session saved " + uuid + "["+usrid+"] : " + session);
//    	
//    	
//    	EAIServerManager eaiServerManager =  EAIServerManager.getInstance();
//    	String serverName = eaiServerManager.getLocalServerName();
//    	
//    	SessionVO sessionVo = new SessionVO();
//    	sessionVo.setUuid(uuid);
//    	sessionVo.setLoginUserId(usrid);
//    	sessionVo.setLoginInstId(serverName);
//    	
//    	SessionInfoVO sessionInfoVO = new SessionInfoVO(usrid);
//    	sessionInfoVO.setSessionId(uuid);
//    	sessionInfoVO.setCreateTime(DatetimeUtil.getCurrentDateTime());
//    	
//    	SessionManager.getInstance().putLogin(session.toString(), sessionVo, sessionInfoVO);
//    			
//    }
    

    public synchronized void sessionClose(IoSession session){
    	try{
	    	String sessionId = session.toString();
	    	String userId = null;
	    	try{
	    		userId = this.uidCache.get(sessionId);
	    		this.uidCache.remove(sessionId);
	    	}catch(NullPointerException e){
	    		logger.error("TcpSessionManager ]  tried to remove Cache , but UIDCache value of ["+sessionId+"] is null ");
	    	}
	    	try{
	    		if(userId != null) this.chnCache.remove(userId);
	    	}catch(NullPointerException e){
	    		logger.error("TcpSessionManager ]  tried to remove Cache , but ChnCache value of ["+sessionId+"] is null ");
	    	}
	    	try{
	    		if(userId != null) {
	    			ChannelSessionFacade.getInstance().removeFromLoginCache(userId);
	    		}
	    	}catch(NullPointerException e){
	    		logger.error("TcpSessionManager ]  tried to remove Cache , but ehCache value of ["+sessionId+"] is null ");
	    	}
    	}catch(Exception e){
    		logger.error("TcpSessionManager ]  Error occured in removing Session Info - " + session);
    	}
    }
    public synchronized String getUid(String sessionId){
    	String uid = uidCache.get(sessionId);
    	return uid;
    }
    public synchronized IoSession getSession(String sessionId){
    	IoSession session = chnCache.get(sessionId);
    	return session;
    }    
} 
