/*
 * Created on 29 déc. 2005
 *
 */
package archean.util.mina;

import java.util.Date;
import java.util.HashMap;
import java.util.List;

import javax.management.NotificationBroadcasterSupport;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.CompositeDataSupport;
import javax.management.openmbean.CompositeType;
import javax.management.openmbean.OpenDataException;
import javax.management.openmbean.OpenType;
import javax.management.openmbean.SimpleType;
import javax.management.openmbean.TabularData;
import javax.management.openmbean.TabularDataSupport;
import javax.management.openmbean.TabularType;

import org.apache.mina.common.IdleStatus;
import org.apache.mina.common.IoFilterChain;
import org.apache.mina.common.IoSession;
import org.apache.mina.filter.LoggingFilter;

/**
 * @author Julien Vermillard - Archean
 *
 */
public class SessionManager extends NotificationBroadcasterSupport implements SessionManagerMBean {
	private IoSession session;
	
	/**
	 * create the session manager
	 * @param session the MINA's session to manage
	 */
	public SessionManager(IoSession session) {
		this.session=session;
	}

	/**
	 * @see archean.util.mina.SessionManagerMBean#isConnected()
	 */
	public boolean isConnected() {
		return session.isConnected();
	}
	

	/**
	 * @see archean.util.mina.SessionManagerMBean#getReadBytes()
	 */
	public long getReadBytes() {
		return session.getReadBytes(); 
	}
	

	/**
	 * @see archean.util.mina.SessionManagerMBean#getWrittenBytes()
	 */
	public long getWrittenBytes() {
		return session.getWrittenBytes();
	}
	

	/**
	 * @see archean.util.mina.SessionManagerMBean#close()
	 */
	public void close() {
		session.close().join();
	}
	
	/**
	 * @see archean.util.mina.SessionManagerMBean#getCreationTime()
	 */
	public Date getCreationTime() {
		return new Date(session.getCreationTime());
	}
	

    /**
     * @see archean.util.mina.SessionManagerMBean#getLastIoTime()
     */
    public Date getLastIoTime() {
    	return new Date(session.getLastIoTime());
    }

    /**
     * @see archean.util.mina.SessionManagerMBean#getLastReadTime()
     */
    public Date getLastReadTime() {
    	return new Date(session.getLastReadTime());
    }


    /**
     * @see archean.util.mina.SessionManagerMBean#getLastWriteTime()
     */
    public Date getLastWriteTime() {
    	return new Date(session.getLastWriteTime());
    }

	/**
	 * @see archean.util.mina.SessionManagerMBean#getReadByteSec()
	 */
	public float getReadByteSec() {
		return ((float)session.getReadBytes())  *1000f / (float)(System.currentTimeMillis()-session.getCreationTime());
	}

	/**
	 * @see archean.util.mina.SessionManagerMBean#getWrittenByteSec()
	 */
	public float getWrittenByteSec() {
		return ((float)session.getWrittenBytes())  *1000f / (float)(System.currentTimeMillis()-session.getCreationTime());
	}
	
	/**
	 * @see archean.util.mina.SessionManagerMBean#getInstalledFilters()
	 */
	public String[] getInstalledFilters() {
		List filters=session.getFilterChain().getAll();
		String[] res=new String[filters.size()];
		for(int i=0;i<res.length;i++) {
			res[i]=((IoFilterChain.Entry)filters.get(i)).getName();
		}
		return res;
	}
	
	
	/**
	 * @see archean.util.mina.SessionManagerMBean#addLastLoggingFilter()
	 */
	public void addLastLoggingFilter() {
		LoggingFilter f=new LoggingFilter();
		session.getFilterChain().addLast("LoggerLast",f);
	}
	
	/**
	 * @see archean.util.mina.SessionManagerMBean#removeLastLoggingFilter()
	 */
	public void removeLastLoggingFilter() {
		
		session.getFilterChain().remove("LoggerLast");
	}

	/**
	 * @see archean.util.mina.SessionManagerMBean#addFirstLoggingFilter()
	 */
	public void addFirstLoggingFilter() {
		LoggingFilter f=new LoggingFilter();
		session.getFilterChain().addFirst("LoggerFirst",f);
	}
	public void removeFirstLoggingFilter() {
		
		session.getFilterChain().remove("LoggerFirst");
	}

	//  IDLE monitoring
	
	/**
	 * @see archean.util.mina.SessionManagerMBean#getReadIdleTime()
	 */
	public long getReadIdleTime() {
		return session.getIdleTimeInMillis(IdleStatus.READER_IDLE);
	}
	
	/**
	 * @see archean.util.mina.SessionManagerMBean#getWriteIdleTime()
	 */
	public long getWriteIdleTime() {
		return session.getIdleTimeInMillis(IdleStatus.WRITER_IDLE);
	}
	
	/**
	 * @see archean.util.mina.SessionManagerMBean#getBothIdleTime()
	 */
	public long getBothIdleTime() {
		return session.getIdleTimeInMillis(IdleStatus.BOTH_IDLE);
	}
	
	// Filters
	
	/**
	 * @see archean.util.mina.SessionManagerMBean#getFilters()
	 */
	public TabularData getFilters() {
		TabularDataSupport res;
		try {
			res=new TabularDataSupport(new TabularType("FilterChain","IO FilterChain",getFilterType(),new String[]{"Name"}));
			List list=session.getFilterChain().getAll();		
			for(int i=0;i<list.size();i++) {
				res.put(getFilter( ((IoFilterChain.Entry)list.get(i)).getName()));
			}
			return res;
		} catch (OpenDataException e) {
			throw new RuntimeException(e);
		}
		
	}
	
	
	// FILTER LIST DATATYPES
	
	private CompositeData getFilter(String name) {
		HashMap<String,String> map=new HashMap<String,String>(); 
		map.put("Name",name);
		map.put("Class",session.getFilterChain().get(name).getClass().getName());

		CompositeDataSupport res;
		try {
			res = new CompositeDataSupport(getFilterType(),map);
			return res;
		} catch (OpenDataException e) {
			throw new RuntimeException(e);
		}
	}
	
	
	private static CompositeType getFilterType() {
		try {
			return new CompositeType("Filter", "MINA IoFilter", new String[] { "Name", "Class" }, new String[] {
					"Name of the filter", "Class" }, new OpenType[] { SimpleType.STRING, SimpleType.STRING });
		} catch (OpenDataException e) {
			throw new RuntimeException(e);
		}

	}
	
	
	// NOTIFICATION
	// (TODO)
}
