package jp.sf.amateras.cookiesession.wrapper;

import java.util.Collections;
import java.util.Enumeration;
import java.util.Map;
import java.util.Set;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionContext;

import jp.sf.amateras.cookiesession.primitive.PrimitiveWrapperUtil;

@SuppressWarnings("deprecation")
public class CookieSession implements HttpSession {

	private static final String CREATION_TIME = CookieSession.class.getName() + ".creationTime";
	private static final String LAST_ACCESSED_TIME = CookieSession.class.getName() + ".lastAccessedTime";

	private boolean isNew;

	private Map<String, Object> attributes;

	private ServletContext context;

	private boolean invalidate = false;

	private int maxInactiveInterval = 0;

	public CookieSession(ServletContext context, Map<String, Object> attributes, boolean isNew){
		this.context = context;
		this.attributes = attributes;
		this.isNew = isNew;

		long currentTime = System.currentTimeMillis();
		if(isNew){
			setAttribute(CREATION_TIME, currentTime);
		}
		setAttribute(LAST_ACCESSED_TIME, currentTime);
	}

	private void checkAvailable(){
		if(invalidate){
			throw new IllegalStateException();
		}
	}

	public long getCreationTime() {
		checkAvailable();
		return (Long) getAttribute(CREATION_TIME);
	}

	public String getId() {
		checkAvailable();
		throw new UnsupportedOperationException();
	}

	public long getLastAccessedTime() {
		checkAvailable();
		return (Long) getAttribute(LAST_ACCESSED_TIME);
	}

	public ServletContext getServletContext() {
		checkAvailable();
		return context;
	}

	public void setMaxInactiveInterval(int interval) {
		checkAvailable();
		this.maxInactiveInterval = interval;

	}

	public int getMaxInactiveInterval() {
		checkAvailable();
		return this.maxInactiveInterval;
	}

	public HttpSessionContext getSessionContext() {
		checkAvailable();
		throw new UnsupportedOperationException();
	}

	public Object getAttribute(String name) {
		checkAvailable();
		return PrimitiveWrapperUtil.getValue(attributes.get(name));
	}

	public Object getValue(String name) {
		checkAvailable();
		return getAttribute(name);
	}

	@SuppressWarnings("rawtypes")
	public Enumeration getAttributeNames() {
		checkAvailable();
		return Collections.enumeration(attributes.keySet());
	}

	public String[] getValueNames() {
		checkAvailable();
		Set<String> keySet = attributes.keySet();
		return keySet.toArray(new String[keySet.size()]);
	}

	public void setAttribute(String name, Object value) {
		checkAvailable();
		attributes.put(name, PrimitiveWrapperUtil.wrap(value));
	}

	public void putValue(String name, Object value) {
		checkAvailable();
		setAttribute(name, value);
	}

	public void removeAttribute(String name) {
		checkAvailable();
		attributes.remove(name);
	}

	public void removeValue(String name) {
		checkAvailable();
		removeAttribute(name);
	}

	public void invalidate() {
		checkAvailable();
		invalidate = true;
	}

	public boolean isNew() {
		checkAvailable();
		return isNew;
	}

	public boolean isInvalidated(){
		return invalidate;
	}

	public Map<String, Object> getAttributes(){
		return attributes;
	}

}
