/*
 * 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.openjpa.util;

import java.io.InputStream;
import java.io.ObjectStreamException;
import java.util.AbstractSet;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

/**
 * Utility methods used by map proxies.
 *
 * @author Abe White
 */
public class ProxyMaps
    extends Proxies {

    /**
     * Call before invoking {@link Map#clear} on super.
     */
    public static void beforeClear(ProxyMap map) {
        dirty(map, true);
        Map.Entry entry;
        for (Iterator itr = map.entrySet().iterator(); itr.hasNext();) {
            entry = (Map.Entry) itr.next();
            removed(map, entry.getKey(), true);
            removed(map, entry.getValue(), false);
        }
    }

    /**
     * Override for {@link Map#keySet}.
     */
    public static Set keySet(ProxyMap map) {
        ProxyEntrySet entries = (ProxyEntrySet) map.entrySet();
        entries.setView(ProxyEntrySet.VIEW_KEYS);
        return entries;
    }

    /**
     * Override for {@link Map#values}.
     */
    public static Collection values(ProxyMap map) {
        ProxyEntrySet entries = (ProxyEntrySet) map.entrySet();
        entries.setView(ProxyEntrySet.VIEW_VALUES);
        return entries;
    }

    /**
     * Wrap the given entry set in a proxy.
     */
    public static Set afterEntrySet(ProxyMap map, Set entries) {
        return new ProxyEntrySetImpl(map, entries);
    }

    /**
     * Call before invoking {@link Map#get} on super.
     */
    public static boolean beforeGet(ProxyMap map, Object key) {
        assertAllowedType(key, map.getKeyType());
        // Java 8 solution/workaround due to containsKey() calling get!=null, which could cause infinite loop
        return map.keySet().contains(key);
    }

    /**
     * Call after invoking {@link Map#get} on super.
     * The potential change is tracked when the get method is called. This change
     * will not translated to an update statement if the retrieved value
     * is not dirty.
     *
     * @param ret the return value from the super's method
     * @param before the return value from {@link #beforeGet}
     * @return the value to return from {@link Map#get}
     */
    public static Object afterGet(ProxyMap map, Object key,
        Object ret, boolean before) {
        if (before) {
            if (map.getChangeTracker() != null)
                ((MapChangeTracker) map.getChangeTracker()).changed(key, ret,
                    ret);
        }
        return ret;
    }


    /**
     * Call before invoking {@link Map#put} on super.
     */
    public static boolean beforePut(ProxyMap map, Object key, Object value) {
        assertAllowedType(key, map.getKeyType());
        assertAllowedType(value, map.getValueType());
        dirty(map, false);
        return map.containsKey(key);
    }

    /**
     * Call after invoking {@link Map#put} on super.
     *
     * @param ret the return value from the super's method
     * @param before the return value from {@link #beforePut}
     * @return the value to return from {@link Map#put}
     */
    public static Object afterPut(ProxyMap map, Object key, Object value,
        Object ret, boolean before) {
        if (before) {
            if (map.getChangeTracker() != null)
                ((MapChangeTracker) map.getChangeTracker()).changed(key, ret,
                    value);
            removed(map, ret, false);
        } else if (map.getChangeTracker() != null)
            ((MapChangeTracker) map.getChangeTracker()).added(key, value);
        return ret;
    }

    /**
     * Call before invoking {@link Properties#setProperty} on super.
     */
    public static boolean beforeSetProperty(ProxyMap map, String key,
        String value) {
        return beforePut(map, key, value);
    }

    /**
     * Call after invoking {@link Properties#setProperty} on super.
     *
     * @param ret the return value from the super's method
     * @param before the return value from {@link #beforeSetProperty}
     * @return the value to return from {@link Properties#setProperty}
     */
    public static Object afterSetProperty(ProxyMap map, String key,
        String value, Object ret, boolean before) {
        return afterPut(map, key, value, ret, before);
    }

    /**
     * Call before invoking {@link Properties#load} on super.
     */
    public static void beforeLoad(ProxyMap map, InputStream in) {
        dirty(map, true);
    }

    /**
     * Call before invoking {@link Properties#loadXML} on super.
     */
    public static void beforeLoadFromXML(ProxyMap map, InputStream in) {
        dirty(map, true);
    }

    /**
     * Overload for {@link Map#putAll}.
     */
    public static void putAll(ProxyMap map, Map values) {
        Map.Entry entry;
        for (Iterator itr = values.entrySet().iterator(); itr.hasNext();) {
            entry = (Map.Entry) itr.next();
            map.put(entry.getKey(), entry.getValue());
        }
    }

    /**
     * Call before invoking {@link Map#remove} on super.
     */
    public static boolean beforeRemove(ProxyMap map, Object key) {
        dirty(map, false);
        return map.containsKey(key);
    }

    /**
     * Call after invoking {@link Map#remove} on super.
     *
     * @param ret the return value from the super's method
     * @param before the return value from {@link #beforeRemove}
     * @return the value to return from {@link Map#remove}
     */
    public static Object afterRemove(ProxyMap map, Object key, Object ret,
        boolean before) {
        if (before) {
            if (map.getChangeTracker() != null)
                ((MapChangeTracker) map.getChangeTracker()).removed(key, ret);
            removed(map, key, true);
            removed(map, ret, false);
        }
        return ret;
    }

    /**
     * Marker interface for a proxy entry set.
     */
    public interface ProxyEntrySet
        extends Set {

        int VIEW_KEYS = 0;
        int VIEW_VALUES = 1;
        int VIEW_ENTRIES = 2;

        /**
         * Set what entry view this set exposes.
         */
        void setView(int view);
    }

    /**
     * Dirtying proxy for map entry set.
     */
    private static class ProxyEntrySetImpl
        extends AbstractSet
        implements ProxyEntrySet {

        private final ProxyMap _map;
        private final Set _entries;
        private int _view = VIEW_ENTRIES;

        /**
         * Supply owning map and delegate entry set on construction.
         */
        public ProxyEntrySetImpl(ProxyMap map, Set entries) {
            _map = map;
            _entries = entries;
        }

        /**
         * View mode.
         */
        public int getView() {
            return _view;
        }

        /**
         * View mode.
         */
        @Override
        public void setView(int view) {
            _view = view;
        }

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

        @Override
        public boolean remove(Object o) {
            if (_view != VIEW_KEYS)
                throw new UnsupportedOperationException();

            if (!_map.containsKey(o))
                return false;
            _map.remove(o);
            return true;
        }

        @Override
        public Iterator iterator() {
            final Iterator itr = _entries.iterator();
            return new Iterator() {
                private Map.Entry _last = null;

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

                @Override
                public Object next() {
                    _last = (Map.Entry) itr.next();
                    switch (_view) {
                        case VIEW_KEYS:
                            return _last.getKey();
                        case VIEW_VALUES:
                            return _last.getValue();
                        default:
                            return _last;
                    }
                }

                @Override
                public void remove() {
                    dirty(_map, false);
                    itr.remove();
                    if (_map.getChangeTracker() != null)
                        ((MapChangeTracker) _map.getChangeTracker()).
                            removed(_last.getKey(), _last.getValue());
                    Proxies.removed(_map, _last.getKey(), true);
                    Proxies.removed(_map, _last.getValue(), false);
                }
            };
        }

        protected Object writeReplace()
            throws ObjectStreamException {
            switch (_view) {
                case VIEW_KEYS:
                    return ((Map) _map).keySet();
                case VIEW_VALUES:
                    return ((Map) _map).values();
                default:
                    return ((Map) _map).entrySet();
            }
        }
    }
}
