/*
 * Copyright 2015-present Open Networking Laboratory
 *
 * Licensed 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.onosproject.persistence.impl;

import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.mapdb.DB;
import org.mapdb.Hasher;
import org.onosproject.store.service.Serializer;

import java.util.Collection;
import java.util.Map;
import java.util.Set;

import static com.google.common.base.Preconditions.checkNotNull;


/**
 * A map implementation that stores and receives all data from a serialized internal map.
 */
public class PersistentMap<K, V> implements Map<K, V> {

    private final Serializer serializer;

    private final org.mapdb.DB database;

    private final Map<byte[], byte[]> items;

    private final String name;

    public PersistentMap(Serializer serializer, DB database, String name) {
        this.serializer = checkNotNull(serializer);
        this.database = checkNotNull(database);
        this.name = checkNotNull(name);

        items = database
                .createHashMap(name)
                .keySerializer(org.mapdb.Serializer.BYTE_ARRAY)
                .valueSerializer(org.mapdb.Serializer.BYTE_ARRAY)
                .hasher(Hasher.BYTE_ARRAY)
                .makeOrGet();
    }

    /**
     * Reads this set in deserialized form into the provided map.
     *
     * @param items the map to be populated
     */
    public void readInto(Map<K, V> items) {
        this.items.forEach((keyBytes, valueBytes) ->
                                   items.put(serializer.decode(keyBytes),
                                             serializer.decode(valueBytes)));
    }

    @Override
    public V remove(Object key) {
        checkNotNull(key, "Key can not be null.");
        V removed = get(key);
        items.remove(serializer.encode(key));
        return removed;
    }

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

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

    @Override
    public boolean containsKey(Object key) {
        checkNotNull(key, "Key cannot be null.");
        return items.containsKey(serializer.encode(key));
    }

    @Override
    public boolean containsValue(Object value) {
        checkNotNull(value, "Value cannot be null.");
        byte[] serialized = serializer.encode(value);
        for (byte[] compareValue : items.values()) {
            boolean same = true;
            if (compareValue == null) {
                same = false;
            } else if (compareValue.length != serialized.length) {
                same = false;
            } else {
                for (int i = 0; i < serialized.length; i++) {
                    if (serialized[i] != compareValue[i]) {
                        same = false;
                        break;
                    }
                }
            }
            if (same) {
                return true;
            }
        }
        return false;
    }

    @Override
    public V get(Object key) {
        checkNotNull(key, "Key cannot be null.");
        byte[] bytes = items.get(serializer.encode(key));
        return bytes == null ? null : serializer.decode(bytes);
    }

    @Override
    public V put(K key, V value) {
        checkNotNull(key, "Key cannot be null.");
        checkNotNull(value, "Value cannot be null.");
        byte[] prevVal = items.put(serializer.encode(key), serializer.encode(value));
        if (prevVal == null) {
            return null;
        }
        return serializer.decode(prevVal);
    }

    @Override
    public void putAll(Map<? extends K, ? extends V> m) {
        checkNotNull(m, "The passed in map cannot be null.");
        m.forEach((k, v) -> items.put(serializer.encode(k), serializer.encode(v)));
    }

    @Override
    public void clear() {
        items.clear();
    }

    @Override
    public Set<K> keySet() {
        Set<K> keys = Sets.newHashSet();
        items.keySet().forEach(k -> keys.add(serializer.decode(k)));
        return keys;
    }

    @Override
    public Collection<V> values() {
        Collection<V> values = Sets.newHashSet();
        items.values().forEach(v -> values.add(serializer.decode(v)));
        return values;
    }

    @Override
    public Set<Entry<K, V>> entrySet() {
        Set<Entry<K, V>> entries = Sets.newHashSet();
        items.entrySet().
                forEach(e -> entries.add(Maps.immutableEntry(serializer.decode(e.getKey()),
                                                             serializer.decode(e.getValue()))));
        return entries;
    }

    @Override
    public boolean equals(Object map) {
        //This is not threadsafe and on larger maps incurs a significant processing cost
        if (!(map instanceof Map)) {
            return false;
        }
        Map asMap = (Map) map;
        if (this.size() != asMap.size()) {
            return false;
        }
        for (Entry entry : this.entrySet()) {
            Object key = entry.getKey();
            if (!asMap.containsKey(key) || !asMap.get(key).equals(entry.getValue())) {
                return false;
            }
        }
        return true;
    }

    @Override
    public int hashCode() {
        return super.hashCode();
    }
}