/*
 * $Id$
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.apache.tiles.request.collection;

import static org.apache.tiles.request.collection.CollectionUtil.*;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.tiles.request.attribute.HasKeys;

/**
 * Wraps an {@link HasKeys} object into a read-only map.
 *
 * @version $Rev$ $Date$
 * @param <V> The type of the values.
 */
public class ReadOnlyEnumerationMap<V> implements Map<String, V> {

    /**
     * The request.
     */
    protected HasKeys<V> request;

    /**
     * Constructor.
     *
     * @param request The request object to use.
     * @since 2.2.0
     */
    public ReadOnlyEnumerationMap(HasKeys<V> request) {
        this.request = request;
    }

    /** {@inheritDoc} */
    public void clear() {
        throw new UnsupportedOperationException();
    }


    /** {@inheritDoc} */
    public boolean containsKey(Object key) {
        return (request.getValue(key(key)) != null);
    }


    /** {@inheritDoc} */
    @SuppressWarnings("unchecked")
    public boolean containsValue(Object value) {
        V realValue = (V) value;
        for (Enumeration<String> keysIt = request.getKeys(); keysIt.hasMoreElements();) {
            if (realValue.equals(request.getValue(keysIt.nextElement()))) {
                return true;
            }
        }
        return false;
    }


    /** {@inheritDoc} */
    public Set<Map.Entry<String, V>> entrySet() {
        return new ReadOnlyEnumerationMapEntrySet();
    }


    /** {@inheritDoc} */
    public V get(Object key) {
        return (request.getValue(key(key)));
    }


    /** {@inheritDoc} */
    public boolean isEmpty() {
        return !request.getKeys().hasMoreElements();
    }


    /** {@inheritDoc} */
    public Set<String> keySet() {
        return new KeySet(request);
    }


    /** {@inheritDoc} */
    public V put(String key, V value) {
        throw new UnsupportedOperationException();
    }


    /** {@inheritDoc} */
    public void putAll(Map<? extends String, ? extends V> map) {
        throw new UnsupportedOperationException();
    }


    /** {@inheritDoc} */
    public V remove(Object key) {
        throw new UnsupportedOperationException();
    }


    /** {@inheritDoc} */
    public int size() {
        return enumerationSize(request.getKeys());
    }


    /** {@inheritDoc} */
    public Collection<V> values() {
        return new ReadOnlyEnumerationMapValuesCollection();
    }


    /** {@inheritDoc} */
    @SuppressWarnings("unchecked")
    @Override
    public boolean equals(Object o) {
        HasKeys<V> otherRequest = ((ReadOnlyEnumerationMap<V>) o).request;
        boolean retValue = true;
        Set<String> otherKeys = new HashSet<String>();
        for (Enumeration<String> attribs = otherRequest.getKeys(); attribs
                .hasMoreElements();) {
            otherKeys.add(attribs.nextElement());
        }
        for (Enumeration<String> attribs = request.getKeys(); attribs
                .hasMoreElements()
                && retValue;) {
            String parameterName = attribs.nextElement();
            retValue = request.getValue(parameterName).equals(
                    otherRequest.getValue(parameterName));
            otherKeys.remove(parameterName);
        }

        return retValue && otherKeys.isEmpty();
    }

    /** {@inheritDoc} */
    @Override
    public int hashCode() {
        int retValue = 0;
        for (Enumeration<String> attribs = request.getKeys(); attribs
                .hasMoreElements();) {
            String parameterName = attribs.nextElement();
            V value = request.getValue(parameterName);
            retValue += parameterName.hashCode() ^ (value == null ? 0 : value.hashCode());
        }
        return retValue;
    }

    /**
     * Entry set implementation for {@link ReadOnlyEnumerationMap}.
     */
    class ReadOnlyEnumerationMapEntrySet implements Set<Map.Entry<String, V>> {

        @Override
        public boolean add(java.util.Map.Entry<String, V> e) {
            throw new UnsupportedOperationException();
        }

        @Override
        public boolean addAll(
                Collection<? extends java.util.Map.Entry<String, V>> c) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void clear() {
            throw new UnsupportedOperationException();
        }

        @SuppressWarnings("unchecked")
        @Override
        public boolean contains(Object o) {
            return containsEntry((java.util.Map.Entry<String, V>) o);
        }

        @SuppressWarnings("unchecked")
        @Override
        public boolean containsAll(Collection<?> c) {
            Collection<Map.Entry<String, V>> realCollection =
                (Collection<Map.Entry<String, V>>) c;
            for (Map.Entry<String, V> entry : realCollection) {
                if (!containsEntry(entry)) {
                    return false;
                }
            }
            return true;
        }

        @Override
        public boolean isEmpty() {
            return ReadOnlyEnumerationMap.this.isEmpty();
        }

        @Override
        public Iterator<java.util.Map.Entry<String, V>> iterator() {
            return new ReadOnlyEnumerationMapEntrySetIterator();
        }

        @Override
        public boolean remove(Object o) {
            throw new UnsupportedOperationException();
        }

        @Override
        public boolean removeAll(Collection<?> c) {
            throw new UnsupportedOperationException();
        }

        @Override
        public boolean retainAll(Collection<?> c) {
            throw new UnsupportedOperationException();
        }

        @Override
        public int size() {
            return ReadOnlyEnumerationMap.this.size();
        }

        @Override
        public Object[] toArray() {
            return toList().toArray();
        }

        @Override
        public <T> T[] toArray(T[] a) {
            return toList().toArray(a);
        }

        /**
         * Checks whether the entry is present.
         *
         * @param entry The entry to check.
         * @return <code>true</code> if the entry is present.
         */
        protected boolean containsEntry(Map.Entry<String, V> entry) {
            V storedValue = request.getValue(key(entry.getKey()));
            return storedValue != null && storedValue.equals(entry.getValue());
        }

        /**
         * Turns this set into a list.
         *
         * @return The list.
         */
        private List<Map.Entry<String, V>> toList() {
            List<Map.Entry<String, V>> entries = new ArrayList<Map.Entry<String, V>>();
            Enumeration<String> names = request.getKeys();
            while (names.hasMoreElements()) {
                entries.add(extractNextEntry(names));
            }
            return entries;
        }

        /**
         * Returns the next entry, given the enumeration.
         *
         * @param names The enumeration to get the next key from.
         * @return The next entry.
         */
        private MapEntry<String, V> extractNextEntry(
                Enumeration<String> names) {
            String name = names.nextElement();
            return new MapEntry<String, V>(name, request.getValue(name),
                    false);
        }

        /**
         * Iterates entries of {@link ReadOnlyEnumerationMap}.
         */
        private class ReadOnlyEnumerationMapEntrySetIterator implements Iterator<Map.Entry<String, V>> {

            /**
             * Enumerates keys.
             */
            private Enumeration<String> namesEnumeration = request.getKeys();

            @Override
            public boolean hasNext() {
                return namesEnumeration.hasMoreElements();
            }

            @Override
            public java.util.Map.Entry<String, V> next() {
                return extractNextEntry(namesEnumeration);
            }

            @Override
            public void remove() {
                throw new UnsupportedOperationException();
            }

        }
    }

    /**
     * Values collection for {@link ReadOnlyEnumerationMap}.
     */
    private class ReadOnlyEnumerationMapValuesCollection implements Collection<V> {

        @Override
        public boolean add(V e) {
            throw new UnsupportedOperationException();
        }

        @Override
        public boolean addAll(Collection<? extends V> c) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void clear() {
            throw new UnsupportedOperationException();
        }

        @Override
        public boolean contains(Object o) {
            return containsValue(o);
        }

        @SuppressWarnings("unchecked")
        @Override
        public boolean containsAll(Collection<?> c) {
            Collection<String> realCollection = (Collection<String>) c;
            List<String> valueList = new ArrayList<String>(realCollection);
            for (Enumeration<String> keysEnum = request.getKeys(); keysEnum.hasMoreElements();) {
                valueList.remove(request.getValue(keysEnum.nextElement()));
                if (valueList.isEmpty()) {
                    return true;
                }
            }
            return false;
        }

        @Override
        public boolean isEmpty() {
            return ReadOnlyEnumerationMap.this.isEmpty();
        }

        @Override
        public Iterator<V> iterator() {
            return new ReadOnlyEnumerationMapValuesCollectionIterator();
        }

        @Override
        public boolean remove(Object o) {
            throw new UnsupportedOperationException();
        }

        @Override
        public boolean removeAll(Collection<?> c) {
            throw new UnsupportedOperationException();
        }

        @Override
        public boolean retainAll(Collection<?> c) {
            throw new UnsupportedOperationException();
        }

        @Override
        public int size() {
            return ReadOnlyEnumerationMap.this.size();
        }

        @Override
        public Object[] toArray() {
            return toList().toArray();
        }

        @Override
        public <T> T[] toArray(T[] a) {
            return toList().toArray(a);
        }

        /**
         * Turns this collection into a list.
         *
         * @return The list.
         */
        private List<V> toList() {
            List<V> entries = new ArrayList<V>();
            Enumeration<String> names = request.getKeys();
            while (names.hasMoreElements()) {
                entries.add(request.getValue(names.nextElement()));
            }
            return entries;
        }

        /**
         * Iterates values of {@link ReadOnlyEnumerationMap}.
         */
        private class ReadOnlyEnumerationMapValuesCollectionIterator implements Iterator<V> {

            /**
             * Enumerates attribute keys.
             */
            private Enumeration<String> namesEnumeration = request.getKeys();

            @Override
            public boolean hasNext() {
                return namesEnumeration.hasMoreElements();
            }

            @Override
            public V next() {
                return request.getValue(namesEnumeration.nextElement());
            }

            @Override
            public void remove() {
                throw new UnsupportedOperationException();
            }
        }
    }
}
