/*******************************************************************************
 * 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.ofbiz.base.util.collections;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import javolution.context.ObjectFactory;
import javolution.lang.Reusable;
import javolution.util.FastList;
import javolution.util.FastMap;
import javolution.util.FastSet;

import org.ofbiz.base.util.UtilGenerics;


/**
 * Map Stack
 *
 */
public class MapContext<K, V> implements Map<K, V>, Reusable, LocalizedMap<V> {

    public static final String module = MapContext.class.getName();

    protected static final ObjectFactory<MapContext<?, ?>> mapStackFactory = new ObjectFactory<MapContext<?, ?>>() {
        @Override
        protected MapContext<?, ?> create() {
            return new MapContext<Object, Object>();
        }
    };

    public static final <K, V> MapContext<K, V> getMapContext() {
        return (MapContext<K, V>) UtilGenerics.<K, V>checkMap(mapStackFactory.object());
    }

    public static <K, V> MapContext<K, V> createMapContext() {
        MapContext<K, V> newValue = MapContext.getMapContext();
        // initialize with a single entry
        newValue.push();
        return newValue;
    }

    @SuppressWarnings("unchecked")
    public static <K, V> MapContext<K, V> createMapContext(Map<K, V> baseMap) {
        MapContext<K, V> newValue = MapContext.getMapContext();
        if (baseMap instanceof MapContext) {
            newValue.stackList.addAll(((MapContext) baseMap).stackList);
        } else {
            newValue.stackList.add(0, baseMap);
        }
        return newValue;
    }

    /** Does a shallow copy of the internal stack of the passed MapContext; enables simultaneous stacks that share common parent Maps */
    public static <K, V> MapContext<K, V> createMapContext(MapContext<K, V> source) {
        MapContext<K, V> newValue = MapContext.getMapContext();
        newValue.stackList.addAll(source.stackList);
        return newValue;
    }

    protected MapContext() {
        super();
    }

    protected List<Map<K, V>> stackList = FastList.newInstance();

    public void reset() {
        stackList = FastList.newInstance();
    }

    /** Puts a new Map on the top of the stack */
    public void push() {
        Map<K, V> newMap = FastMap.newInstance();
        this.stackList.add(0,newMap);
    }

    /** Puts an existing Map on the top of the stack (top meaning will override lower layers on the stack) */
    public void push(Map<K, V> existingMap) {
        if (existingMap == null) {
            throw new IllegalArgumentException("Error: cannot push null existing Map onto a MapContext");
        }
        this.stackList.add(0, existingMap);
    }

    /** Puts an existing Map on the BOTTOM of the stack (bottom meaning will be overriden by lower layers on the stack, ie everything else already there) */
    public void addToBottom(Map<K, V> existingMap) {
        if (existingMap == null) {
            throw new IllegalArgumentException("Error: cannot add null existing Map to bottom of a MapContext");
        }
        this.stackList.add(existingMap);
    }

    /** Remove and returns the Map from the top of the stack; if there is only one Map on the stack it returns null and does not remove it */
    public Map<K, V> pop() {
        // always leave at least one Map in the List, ie never pop off the last Map
        if (this.stackList.size() > 1) {
            return stackList.remove(0);
        } else {
            return null;
        }
    }

    /**
     * Creates a MapContext object that has the same Map objects on its stack;
     * meant to be used to enable a
     * situation where a parent and child context are operating simultaneously
     * using two different MapContext objects, but sharing the Maps in common
     */
    public MapContext<K, V> standAloneStack() {
        MapContext<K, V> standAlone = MapContext.createMapContext(this);
        return standAlone;
    }

    /**
     * Creates a MapContext object that has the same Map objects on its stack,
     * but with a new Map pushed on the top; meant to be used to enable a
     * situation where a parent and child context are operating simultaneously
     * using two different MapContext objects, but sharing the Maps in common
     */
    public MapContext<K, V> standAloneChildStack() {
        MapContext<K, V> standAloneChild = MapContext.createMapContext(this);
        standAloneChild.push();
        return standAloneChild;
    }

    /* (non-Javadoc)
     * @see java.util.Map#size()
     */
    public int size() {
        // a little bit tricky; to represent the apparent size we need to aggregate all keys and get a count of unique keys
        // this is a bit of a slow way, but gets the best number possible
        Set<K> keys = this.keySet();
        return keys.size();
    }

    /* (non-Javadoc)
     * @see java.util.Map#isEmpty()
     */
    public boolean isEmpty() {
        // walk the stackList and if any is not empty, return false; otherwise return true
        for (Map<K, V> curMap: this.stackList) {
            if (!curMap.isEmpty()) {
                return false;
            }
        }
        return true;
    }

    /* (non-Javadoc)
     * @see java.util.Map#containsKey(java.lang.Object)
     */
    public boolean containsKey(Object key) {
        // walk the stackList and for the first place it is found return true; otherwise refurn false
        for (Map<K, V> curMap: this.stackList) {
            if (curMap.containsKey(key)) {
                return true;
            }
        }
        return false;
    }

    /* (non-Javadoc)
     * @see java.util.Map#containsValue(java.lang.Object)
     */
    public boolean containsValue(Object value) {
        // walk the stackList and the entries for each Map and if nothing is in for the current key, consider it an option, otherwise ignore
        Set<K> resultKeySet = FastSet.newInstance();
        for (Map<K, V> curMap: this.stackList) {
            for (Map.Entry<K, V> curEntry: curMap.entrySet()) {
                if (!resultKeySet.contains(curEntry.getKey())) {
                    resultKeySet.add(curEntry.getKey());
                    if (value == null) {
                        if (curEntry.getValue() == null) {
                            return true;
                        }
                    } else {
                        if (value.equals(curEntry.getValue())) {
                            return true;
                        }
                    }
                }
            }
        }
        return false;
    }

    /* (non-Javadoc)
     * @see java.util.Map#get(java.lang.Object)
     */
    public V get(Object key) {
        // walk the stackList and for the first place it is found return true; otherwise refurn false
        for (Map<K, V> curMap: this.stackList) {
            // only return if the curMap contains the key, rather than checking for null; this allows a null at a lower level to override a value at a higher level
            if (curMap.containsKey(key)) {
                return curMap.get(key);
            }
        }
        return null;
    }

    /* (non-Javadoc)
     * @see org.ofbiz.base.util.collections.LocalizedMap#get(java.lang.String, java.util.Locale)
     */
    public V get(String name, Locale locale) {
        // walk the stackList and for the first place it is found return true; otherwise refurn false
        for (Map<K, V> curMap: this.stackList) {
            // only return if the curMap contains the key, rather than checking for null; this allows a null at a lower level to override a value at a higher level
            if (curMap.containsKey(name)) {
                if (curMap instanceof LocalizedMap<?>) {
                    LocalizedMap<V> lmap = UtilGenerics.cast(curMap);
                    return lmap.get(name, locale);
                } else {
                    return curMap.get(name);
                }
            }
        }
        return null;
    }

    /* (non-Javadoc)
     * @see java.util.Map#put(java.lang.Object, java.lang.Object)
     */
    public V put(K key, V value) {
        // all write operations are local: only put in the Map on the top of the stack
        Map<K, V> currentMap = this.stackList.get(0);
        return currentMap.put(key, value);
    }

    /* (non-Javadoc)
     * @see java.util.Map#remove(java.lang.Object)
     */
    public V remove(Object key) {
        // all write operations are local: only remove from the Map on the top of the stack
        Map<K, V> currentMap = this.stackList.get(0);
        return currentMap.remove(key);
    }

    /* (non-Javadoc)
     * @see java.util.Map#putAll(java.util.Map)
     */
    public void putAll(Map<? extends K, ? extends V> arg0) {
        // all write operations are local: only put in the Map on the top of the stack
        Map<K, V> currentMap = this.stackList.get(0);
        currentMap.putAll(arg0);
    }

    /* (non-Javadoc)
     * @see java.util.Map#clear()
     */
    public void clear() {
        // all write operations are local: only clear the Map on the top of the stack
        this.stackList.get(0).clear();
    }

    /* (non-Javadoc)
     * @see java.util.Map#keySet()
     */
    public Set<K> keySet() {
        // walk the stackList and aggregate all keys
        Set<K> resultSet = FastSet.newInstance();
        for (Map<K, V> curMap: this.stackList) {
            resultSet.addAll(curMap.keySet());
        }
        return Collections.unmodifiableSet(resultSet);
    }

    /* (non-Javadoc)
     * @see java.util.Map#values()
     */
    public Collection<V> values() {
        // walk the stackList and the entries for each Map and if nothing is in for the current key, put it in
        Set<K> resultKeySet = FastSet.newInstance();
        List<V> resultValues = FastList.newInstance();
        for (Map<K, V> curMap: this.stackList) {
            for (Map.Entry<K, V> curEntry: curMap.entrySet()) {
                if (!resultKeySet.contains(curEntry.getKey())) {
                    resultKeySet.add(curEntry.getKey());
                    resultValues.add(curEntry.getValue());
                }
            }
        }
        return Collections.unmodifiableCollection(resultValues);
    }

    /* (non-Javadoc)
     * @see java.util.Map#entrySet()
     */
    public Set<Map.Entry<K, V>> entrySet() {
        // walk the stackList and the entries for each Map and if nothing is in for the current key, put it in
        Set<K> resultKeySet = FastSet.newInstance();
        Set<Map.Entry<K, V>> resultEntrySet = FastSet.newInstance();
        for (Map<K, V> curMap: this.stackList) {
            for (Map.Entry<K, V> curEntry: curMap.entrySet()) {
                if (!resultKeySet.contains(curEntry.getKey())) {
                    resultKeySet.add(curEntry.getKey());
                    resultEntrySet.add(curEntry);
                }
            }
        }
        return Collections.unmodifiableSet(resultEntrySet);
    }

    @Override
    public String toString() {
        StringBuilder fullMapString = new StringBuilder();
        int curLevel = 0;
        for (Map<K, V> curMap: this.stackList) {
            fullMapString.append("============================== Start stack level " + curLevel + "\n");
            for (Map.Entry<K, V> curEntry: curMap.entrySet()) {

                fullMapString.append("==>[");
                fullMapString.append(curEntry.getKey());
                fullMapString.append("]:");
                // skip the instances of MapContext to avoid infinite loop
                if (curEntry.getValue() instanceof MapContext<?, ?>) {
                    fullMapString.append("<Instance of MapContext, not printing to avoid infinite recursion>");
                } else {
                    fullMapString.append(curEntry.getValue());
                }
                fullMapString.append("\n");
            }
            fullMapString.append("============================== End stack level " + curLevel + "\n");
            curLevel++;
        }
        return fullMapString.toString();
    }
}
