/*
 * Copyright 2016-present Open Networking Foundation
 *
 * 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.store.primitives;

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

import java.util.Objects;
import java.util.function.Function;

import org.onlab.util.ByteArraySizeHashPrinter;

import com.google.common.base.MoreObjects;

/**
 * Map update operation.
 *
 * @param <K> map key type
 * @param <V> map value type
 */
public final class MapUpdate<K, V> {

    /**
     * Type of database update operation.
     */
    public enum Type {

        /**
         * Acquires a read lock on a key.
         * <p>
         * This record type will check to ensure that the lock version matches the current version for the key
         * in the map and acquire a read lock on the key for the duration of the transaction.
         */
        LOCK,

        /**
         * Checks the version of a key without locking the key.
         * <p>
         * This record type will perform a simple version check during the prepare phase of the two-phase commit
         * protocol to ensure that the key has not changed during a transaction.
         */
        VERSION_MATCH,

        /**
         * Updates an entry if the current version matches specified version.
         */
        PUT_IF_VERSION_MATCH,

        /**
         * Removes an entry if the current version matches specified version.
         */
        REMOVE_IF_VERSION_MATCH,
    }

    private Type type;
    private K key;
    private V value;
    private long version = -1;

    /**
     * Returns the type of update operation.
     * @return type of update.
     */
    public Type type() {
        return type;
    }

    /**
     * Returns the item key being updated.
     * @return item key
     */
    public K key() {
        return key;
    }

    /**
     * Returns the new value.
     * @return item's target value.
     */
    public V value() {
        return value;
    }

    /**
     * Returns the expected current version in the database for the key.
     * @return expected version.
     */
    public long version() {
        return version;
    }

    /**
     * Transforms this instance into an instance of different paramterized types.
     *
     * @param keyMapper transcoder for key type
     * @param valueMapper transcoder to value type
     * @return new instance
     * @param <S> key type of returned instance
     * @param <T> value type of returned instance
     */
    public <S, T> MapUpdate<S, T> map(Function<K, S> keyMapper, Function<V, T> valueMapper) {
        return MapUpdate.<S, T>newBuilder()
                .withType(type)
                .withKey(keyMapper.apply(key))
                .withValue(value == null ? null : valueMapper.apply(value))
                .withVersion(version)
                .build();
    }

    @Override
    public int hashCode() {
        return Objects.hash(type, key, value, version);
    }

    @Override
    public boolean equals(Object object) {
        if (object instanceof MapUpdate) {
            MapUpdate that = (MapUpdate) object;
            return this.type == that.type
                    && Objects.equals(this.key, that.key)
                    && Objects.equals(this.value, that.value)
                    && Objects.equals(this.version, that.version);
        }
        return false;
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(this)
            .add("type", type)
            .add("key", key)
            .add("value", value instanceof byte[] ? new ByteArraySizeHashPrinter((byte[]) value) : value)
            .add("version", version)
            .toString();
    }

    /**
     * Creates a new builder instance.
     *
     * @param <K> key type
     * @param <V> value type
     * @return builder.
     */
    public static <K, V> Builder<K, V> newBuilder() {
        return new Builder<>();
    }

    /**
     * MapUpdate builder.
     *
     * @param <K> key type
     * @param <V> value type
     */
    public static final class Builder<K, V> {

        private MapUpdate<K, V> update = new MapUpdate<>();

        public MapUpdate<K, V> build() {
            validateInputs();
            return update;
        }

        public Builder<K, V> withType(Type type) {
            update.type = checkNotNull(type, "type cannot be null");
            return this;
        }

        public Builder<K, V> withKey(K key) {
            update.key = checkNotNull(key, "key cannot be null");
            return this;
        }

        public Builder<K, V> withValue(V value) {
            update.value = value;
            return this;
        }

        public Builder<K, V> withVersion(long version) {
            update.version = version;
            return this;
        }

        private void validateInputs() {
            checkNotNull(update.type, "type must be specified");
            switch (update.type) {
                case VERSION_MATCH:
                    break;
                case LOCK:
                    checkNotNull(update.key, "key must be specified");
                    checkState(update.version >= 0, "version must be specified");
                    break;
                case PUT_IF_VERSION_MATCH:
                    checkNotNull(update.key, "key must be specified");
                    checkNotNull(update.value, "value must be specified.");
                    checkState(update.version >= 0, "version must be specified");
                    break;
                case REMOVE_IF_VERSION_MATCH:
                    checkNotNull(update.key, "key must be specified");
                    checkState(update.version >= 0, "version must be specified");
                    break;
                default:
                    throw new IllegalStateException("Unknown operation type");
            }

        }
    }
}
