/*
 * 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.myfaces.test.mock;

import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;


/**
 * NOTE: Class copied from trinidad to be used on MockFlash.
 * <p/>
 * Map that wraps another to provide an isolated namespace using
 * a prefix.  This is especially handy for storing properties on
 * the session in a structured manner without putting them into
 * a true "Map" - because storing in a Map breaks session failover.
 * (Session failover won't trigger on mutations of contained objects.)
 * <p/>
 * Note that there is a potential design flaw;  if you create a SubKeyMap
 * for "mypackage.foo" and for "mypackage.foo.bar", all the keys in the
 * latter will actually show up in the former (prefixed by ".bar").  This
 * "flaw" is actually relied on by PageFlowScopeMap (since it provides
 * a handy way to clear out all descendents), so don't "fix" it!
 * 
 * @since 1.0.0
 */
final class MockSubKeyMap<V> extends AbstractMap<String, V>
{
    public MockSubKeyMap(Map<String, Object> base, String prefix)
    {
        if (base == null)
        {
            throw new NullPointerException();
        }
        if (prefix == null)
        {
            throw new NullPointerException();
        }

        // Optimize the scenario where we're wrapping another SubKeyMap
        if (base instanceof MockSubKeyMap)
        {
            _base = ((MockSubKeyMap) base)._base;
            _prefix = ((MockSubKeyMap) base)._prefix + prefix;
        }
        else
        {
            _base = base;
            _prefix = prefix;
        }
    }

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

    @Override
    public V get(Object key)
    {
        key = _getBaseKey(key);
        return (V) _base.get(key);
    }

    @Override
    public V put(String key, V value)
    {
        key = _getBaseKey(key);
        return (V) _base.put(key, value);
    }

    @Override
    public V remove(Object key)
    {
        key = _getBaseKey(key);
        return (V) _base.remove(key);
    }

    @Override
    public boolean containsKey(Object key)
    {
        if (!(key instanceof String))
        {
            return false;
        }

        return _base.containsKey(_getBaseKey(key));
    }

    @Override
    public Set<Map.Entry<String, V>> entrySet()
    {
        if (_entrySet == null)
        {
            _entrySet = new Entries<V>();
        }
        return _entrySet;
    }

    private String _getBaseKey(Object key)
    {
        if (key == null)
        {
            throw new NullPointerException();
        }
        // Yes, I want a ClassCastException if it's not a String
        return _prefix + ((String) key);
    }

    private List<String> _gatherKeys()
    {
        List<String> list = new ArrayList<String>();
        for (String key : _base.keySet())
        {
            if (key != null && key.startsWith(_prefix))
            {
                list.add(key);
            }
        }

        return list;
    }

    //
    // Set implementation for SubkeyMap.entrySet()
    //

    private class Entries<V> extends AbstractSet<Map.Entry<String, V>>
    {
        public Entries()
        {
        }

        @Override
        public Iterator<Map.Entry<String, V>> iterator()
        {
            // Sadly, if you just try to use a filtering approach
            // on the iterator, you'll get concurrent modification
            // exceptions.  Consequently, gather the keys in a list
            // and iterator over that.
            List<String> keyList = _gatherKeys();
            return new EntryIterator<V>(keyList.iterator());
        }

        @Override
        public int size()
        {
            int size = 0;
            for (String key : _base.keySet())
            {
                if (key != null && key.startsWith(_prefix))
                {
                    size++;
                }
            }

            return size;
        }

        @Override
        public boolean isEmpty()
        {
            Iterator<String> keys = _base.keySet().iterator();
            while (keys.hasNext())
            {
                String key = keys.next();
                // Short-circuit:  the default implementation would always
                // need to iterate to find the total size.
                if (key != null && key.startsWith(_prefix))
                {
                    return false;
                }
            }

            return true;
        }

        @Override
        public void clear()
        {
            Iterator<String> keys = _base.keySet().iterator();
            while (keys.hasNext())
            {
                String key = keys.next();
                if (key != null && key.startsWith(_prefix))
                {
                    keys.remove();
                }
            }
        }
    }

    private class EntryIterator<V> implements Iterator<Map.Entry<String, V>>
    {
        public EntryIterator(Iterator<String> iterator)
        {
            _iterator = iterator;
        }

        public boolean hasNext()
        {
            return _iterator.hasNext();
        }

        public Map.Entry<String, V> next()
        {
            String baseKey = _iterator.next();
            _currentKey = baseKey;
            return new Entry<V>(baseKey);
        }

        public void remove()
        {
            if (_currentKey == null)
            {
                throw new IllegalStateException();
            }

            _base.remove(_currentKey);

            _currentKey = null;
        }

        private Iterator<String> _iterator;
        private String _currentKey;
    }

    private class Entry<V> implements Map.Entry<String, V>
    {
        public Entry(String baseKey)
        {
            _baseKey = baseKey;
        }

        public String getKey()
        {
            if (_key == null)
            {
                _key = _baseKey.substring(_prefix.length());
            }
            return _key;
        }

        public V getValue()
        {
            return (V) _base.get(_baseKey);
        }

        public V setValue(V value)
        {
            return (V) _base.put(_baseKey, value);
        }

        @SuppressWarnings("unchecked")
        @Override
        public boolean equals(Object o)
        {
            if (!(o instanceof Map.Entry))
            {
                return false;
            }
            Map.Entry<String, V> e = (Map.Entry<String, V>) o;
            return _equals(getKey(), e.getKey())
                    && _equals(getValue(), e.getValue());
        }

        @Override
        public int hashCode()
        {
            Object key = getKey();
            Object value = getValue();
            return ((key == null) ? 0 : key.hashCode())
                    ^ ((value == null) ? 0 : value.hashCode());
        }

        private String _baseKey;
        private String _key;
    }

    static private boolean _equals(Object a, Object b)
    {
        if (a == null)
        {
            return b == null;
        }
        return a.equals(b);
    }

    private final Map<String, Object> _base;
    private final String _prefix;
    private Set<Map.Entry<String, V>> _entrySet;

}
