/*
 * 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 (Object o : map.entrySet()) {
            entry = (Map.Entry) o;
            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 (Object o : values.entrySet()) {
            entry = (Map.Entry) o;
            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();
            }
        }
    }
}
