/*
 * Copyright 2014 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.onlab.onos.store.service.impl;

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

import java.util.Map;

import org.onlab.onos.store.serializers.StoreSerializer;
import org.onlab.onos.store.service.DatabaseAdminService;
import org.onlab.onos.store.service.DatabaseService;
import org.onlab.onos.store.service.VersionedValue;

import com.google.common.base.Function;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.FluentIterable;

/**
 * Map like interface wrapper around DatabaseService.
 *
 * @param <K> Key type of the map.
 *       The type must have toString(), which can uniquely identify the entry.
 * @param <V> Value type
 */
public class CMap<K, V> {

    @SuppressWarnings("unused")
    private final DatabaseAdminService dbAdminService;

    private final DatabaseService dbService;

    private final String tableName;
    private final StoreSerializer serializer;

    private final LoadingCache<K, String> keyCache;

    /**
     * Creates a CMap instance.
     * It will create the table if necessary.
     *
     * @param dbAdminService DatabaseAdminService to use for this instance
     * @param dbService DatabaseService to use for this instance
     * @param tableName table which this Map corresponds to
     * @param serializer Value serializer
     */
    public CMap(DatabaseAdminService dbAdminService,
                DatabaseService dbService,
                String tableName,
                StoreSerializer serializer) {

        this.dbAdminService = checkNotNull(dbAdminService);
        this.dbService = checkNotNull(dbService);
        this.tableName = checkNotNull(tableName);
        this.serializer = checkNotNull(serializer);

        if (!dbAdminService.listTables().contains(tableName)) {
            dbAdminService.createTable(tableName);
        }

        keyCache = CacheBuilder.newBuilder()
                    .softValues()
                    .build(new CacheLoader<K, String>() {

                        @Override
                        public String load(K key) {
                            return key.toString();
                        }
                    });
    }

    protected String sK(K key) {
        return keyCache.getUnchecked(key);
    }

    protected byte[] sV(V val) {
        return serializer.encode(val);
    }

    protected V dV(byte[] valBytes) {
        return serializer.decode(valBytes);
    }

    /**
     * Puts an entry to the map, if not already present.
     *
     * @param key the key of the value to put if absent
     * @param value the value to be put if previous value does not exist
     * @return true if put was successful.
     */
    public boolean putIfAbsent(K key, V value) {
        return dbService.putIfAbsent(tableName, sK(key), sV(value));
    }

    /**
     * Removes an entry associated to specified key.
     *
     * @param key key of the value to remove
     * @return previous value in the map for the key
     */
    public V remove(K key) {
        VersionedValue removed = dbService.remove(tableName, sK(key));
        if (removed == null) {
            return null;
        }
        return dV(removed.value());
    }

    /**
     * Returns the size of the map.
     *
     * @return size of the map
     */
    public long size() {
        // TODO this is very inefficient
        return dbService.getAll(tableName).size();
    }

    /**
     * Returns all the values contained in the map.
     *
     * @return values containd in this map
     */
    public Iterable<V> values() {
        Map<String, VersionedValue> all = dbService.getAll(tableName);
        return FluentIterable.from(all.values())
                .transform(new Function<VersionedValue, V>() {

                    @Override
                    public V apply(VersionedValue input) {
                        if (input == null) {
                            return null;
                        }
                        return dV(input.value());
                    }
                })
                .filter(notNull());
    }

    /**
     * Gets the value in the map.
     *
     * @param key to get from the map
     * @return value associated with the key, null if not such entry
     */
    public V get(K key) {
        VersionedValue vv = dbService.get(tableName, sK(key));
        if (vv == null) {
            return null;
        }
        return dV(vv.value());
    }

    /**
     * Replaces the value in the map if the value matches the expected.
     *
     * @param key of the entry to replace
     * @param oldVal value expected to be in the map
     * @param newVal value to be replaced with
     * @return true if successfully replaced
     */
    public boolean replace(K key, V oldVal, V newVal) {
        return dbService.putIfValueMatches(tableName, sK(key), sV(oldVal), sV(newVal));
    }

    /**
     * Puts a value int the map.
     *
     * @param key key with which the specified value is to be associated
     * @param value value to be associated with the specified key
     * @return previous value or null if not such entry
     */
    public V put(K key, V value) {
        VersionedValue vv = dbService.put(tableName, sK(key), sV(value));
        if (vv == null) {
            return null;
        }
        return dV(vv.value());
    }
}