/*
 * Copyright 2015 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.store.service;

import com.google.common.base.MoreObjects;
import com.google.common.collect.ComparisonChain;
import org.onosproject.store.Timestamp;

import java.util.Objects;

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

/**
 * A logical timestamp that derives its value from two input values. The first
 * value always takes precedence over the second value when comparing timestamps.
 */
public class MultiValuedTimestamp<T extends Comparable<T>, U extends Comparable<U>>
        implements Timestamp {

    private final T value1;
    private final U value2;

    /**
     * Creates a new timestamp based on two values. The first value has higher
     * precedence than the second when comparing timestamps.
     *
     * @param value1 first value
     * @param value2 second value
     */
    public MultiValuedTimestamp(T value1, U value2) {
        this.value1 = checkNotNull(value1);
        this.value2 = checkNotNull(value2);
    }

    @Override
    public int compareTo(Timestamp o) {
        checkArgument(o instanceof MultiValuedTimestamp,
                      "Must be MultiValuedTimestamp", o);
        MultiValuedTimestamp that = (MultiValuedTimestamp) o;

        return ComparisonChain.start()
                .compare(this.value1, that.value1)
                .compare(this.value2, that.value2)
                .result();
    }

    @Override
    public int hashCode() {
        return Objects.hash(value1, value2);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (!(obj instanceof MultiValuedTimestamp)) {
            return false;
        }
        MultiValuedTimestamp that = (MultiValuedTimestamp) obj;
        return Objects.equals(this.value1, that.value1) &&
                Objects.equals(this.value2, that.value2);
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(getClass())
                .add("value1", value1)
                .add("value2", value2)
                .toString();
    }

    /**
     * Returns the first value.
     *
     * @return first value
     */
    public T value1() {
        return value1;
    }

    /**
     * Returns the second value.
     *
     * @return second value
     */
    public U value2() {
        return value2;
    }

    // Default constructor for serialization
    @SuppressWarnings("unused")
    private MultiValuedTimestamp() {
        this.value1 = null;
        this.value2 = null;
    }
}
