/*
 * Copyright 2004-2005 the original author or authors.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.codehaus.groovy.grails.web.metaclass;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.*;
/**
 * A dynamic property that adds a "session" map to a controller for accessing the Http Session
 * 
 * @author Graeme Rocher
 * @since Oct 24, 2005
 */
public class GetSessionDynamicProperty extends AbstractDynamicControllerProperty {

	public static final String PROPERTY_NAME = "session";
	private HttpSessionMap sessionMap;

	public GetSessionDynamicProperty(HttpServletRequest request, HttpServletResponse response) {
		super(PROPERTY_NAME, request, response);
		this.sessionMap = new HttpSessionMap();
	}

	public Object get(Object object) {
		return this.sessionMap;
	}

	public void set(Object object, Object newValue) {
		throw new UnsupportedOperationException("Property '" + PROPERTY_NAME + "' of class '"+object.getClass()+"' is read-only!" );
	}
	
	/**
	 * Wraps the HttpSessoin in a map
	 * 
	 * @author Graeme Rocher
	 * @since Oct 24, 2005
	 */
	private class HttpSessionMap implements Map {
				
		HttpSession session = null;
		
		public int size() {
			if(session == null)
				return 0;			
			// count as there is no way to access size from the session directly
			int count = 0;
			for(Enumeration e = session.getAttributeNames();e.hasMoreElements();count++) {}
			return count;
		}

		public boolean isEmpty() {
            if(session == null)
               return true;

           Enumeration e = session.getAttributeNames();
           return !e.hasMoreElements();
       }

		public boolean containsKey(Object key) {
			if(!(key instanceof String))
				throw new IllegalArgumentException("The 'session' property key '"+key+"' must be a string value");
			
			if(session == null || session.isNew())
				return false;
			
			Object attr = session.getAttribute((String)key);
			if(attr == null)
				return false;
			else
				return true;
		}

		public boolean containsValue(Object value) {
			if(session == null)
				return false;
			
			for(Enumeration e = session.getAttributeNames();e.hasMoreElements();) {
				String currentKey = (String)e.nextElement();
				Object current = session.getAttribute(currentKey);
				if(current.equals(value))
					return true;
			}			
			return false;
		}

		public Object get(Object key) {
			if(!(key instanceof String))
				throw new IllegalArgumentException("The 'session' property key '"+key+"' must be a string value");
			

           if(session == null)
               session = request.getSession(false);
           if(session == null)
               return null;

			return session.getAttribute((String)key);
		}

		public Object put(Object key, Object value) {
			if(!(key instanceof String))
				throw new IllegalArgumentException("The 'session' property key '"+key+"' must be a string value");
			
			if(session == null)
				session = request.getSession();
			
			session.setAttribute((String)key, value);
			return value;
		}

		public Object remove(Object key) {
			if(!(key instanceof String))
				throw new IllegalArgumentException("The 'session' property key '"+key+"' must be a string value");

			if(session == null)
				return null;
			
			Object value = session.getAttribute((String)key);
			if(value != null)
				session.removeAttribute((String)key);
			
			return value;
		}

		public void putAll(Map sessionMap) {
			for (Iterator i = sessionMap.keySet().iterator(); i.hasNext();) {
				String currentKey = (String) i.next();
				put(currentKey,sessionMap.get(currentKey));			
			}
		}

		public void clear() {
			if(session == null)
				return;
			
			for(Enumeration e = session.getAttributeNames();e.hasMoreElements();) {
				String current = (String)e.nextElement();
				session.removeAttribute(current);
			}
		}

		public Set keySet() {
			if(session == null || session.isNew())
				return Collections.EMPTY_SET;
			
			Set keySet = new HashSet();
			for(Enumeration e = session.getAttributeNames();e.hasMoreElements();) {
				String current = (String)e.nextElement();
				keySet.add(current);
			}			
			return keySet;
		}

		public Collection values() {
			throw new UnsupportedOperationException("Method 'values()' is not support by session Map." );
		}

		public Set entrySet() {
			throw new UnsupportedOperationException("Method 'entrySet()' is not support by session Map." );
		}		
	}
}
