/*
 * Copyright 2019, TeamDev. All rights reserved.
 *
 * Redistribution and use in source and/or binary forms, with or without
 * modification, must retain the above copyright notice and the following
 * disclaimer.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package io.spine.protobuf;

import com.google.common.base.Converter;
import com.google.protobuf.Timestamp;
import io.spine.string.Stringifiers;
import io.spine.time.temporal.TimestampTemporal;

import java.io.Serializable;
import java.time.Instant;

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

/**
 * Utilities class for working with {@link com.google.protobuf.Timestamp Timestamp} values in
 * addition to those available from {@link com.google.protobuf.util.Timestamps Timestamps} utility
 * class from the Protobuf Util library.
 *
 * @deprecated Use {@link TimestampTemporal} instead. Also, consider domain-specific types for time
 *         representation.
 */
@Deprecated
public final class Timestamps2 {

    /** Prevent instantiation of this utility class. */
    private Timestamps2() {
    }

    /**
     * Converts the passed timestamp to {@code Instant}.
     */
    @Deprecated
    public static Instant toInstant(Timestamp timestamp) {
        checkNotNull(timestamp);
        return InstantConverter.INSTANCE.reverse()
                                        .convert(timestamp);
    }

    /**
     * Calculates if the {@code timestamp} is between the {@code start} and
     * {@code finish} timestamps.
     *
     * @param timestamp
     *         the timestamp to check if it is between the {@code start} and {@code finish}
     * @param start
     *         the first point in time, must be before the {@code finish} timestamp
     * @param finish
     *         the second point in time, must be after the {@code start} timestamp
     * @return {@code true} if the {@code timestamp} is after the {@code start} and before
     *         the {@code finish} timestamps, {@code false} otherwise
     */
    @Deprecated
    public static boolean isBetween(Timestamp timestamp, Timestamp start, Timestamp finish) {
        TimestampTemporal temporal = TimestampTemporal.from(timestamp);
        TimestampTemporal startTemporal = TimestampTemporal.from(start);
        TimestampTemporal finishTemporal = TimestampTemporal.from(finish);
        return temporal.isBetween(startTemporal, finishTemporal);
    }

    /**
     * Calculates if {@code timestamp} is later {@code thanTime} timestamp.
     *
     * @param timestamp
     *         the timestamp to check if it is later then {@code thanTime}
     * @param thanTime
     *         the first point in time which is supposed to be before the {@code timestamp}
     * @return {@code true} if the {@code timestamp} is later than {@code thanTime} timestamp,
     *         {@code false} otherwise
     */
    @Deprecated
    public static boolean isLaterThan(Timestamp timestamp, Timestamp thanTime) {
        TimestampTemporal later = TimestampTemporal.from(timestamp);
        TimestampTemporal earlier = TimestampTemporal.from(thanTime);
        return later.isLaterThan(earlier);
    }

    /**
     * Parses a timestamp from an RFC-3339 date-time string.
     *
     * <p>Unlike {@link com.google.protobuf.util.Timestamps#parse(String) its Protobuf counterpart}
     * this method does not throw a checked exception.
     *
     * @throws IllegalArgumentException
     *         if the string is not of required format
     */
    @Deprecated
    public static Timestamp parse(String str) {
        checkNotNull(str);
        return Stringifiers.forTimestamp()
                           .reverse()
                           .convert(str);
    }

    /**
     * Creates {@code Timestamp} by the passed {@code Instant} value.
     */
    @Deprecated
    public static Timestamp fromInstant(Instant instant) {
        checkNotNull(instant);
        return InstantConverter.INSTANCE.convert(instant);
    }

    /**
     * Obtains converter of {@code Timestamp}s to {@code Instant}s.
     */
    @Deprecated
    public static Converter<Instant, Timestamp> converter() {
        return InstantConverter.INSTANCE;
    }

    /**
     * Converts {@code Timestamp} to {@code Instant}.
     */
    @Deprecated
    private static final class InstantConverter extends Converter<Instant, Timestamp>
            implements Serializable {

        private static final long serialVersionUID = 0L;
        private static final InstantConverter INSTANCE = new InstantConverter();

        @Override
        protected Timestamp doForward(Instant value) {
            checkNotNull(value);
            Timestamp result = Timestamp
                    .newBuilder()
                    .setSeconds(value.getEpochSecond())
                    .setNanos(value.getNano())
                    .build();
            return result;
        }

        @Override
        protected Instant doBackward(Timestamp value) {
            checkNotNull(value);
            Instant result = Instant.ofEpochSecond(value.getSeconds(), value.getNanos());
            return result;
        }

        @Override
        public String toString() {
            return "Timestamps2.converter()";
        }

        private Object readResolve() {
            return INSTANCE;
        }
    }
}

@@ -1132,198 +1132,66 @@
 ine.
-string.Stringifiers;%0Aimport io.spine.time.temporal.TimestampTemporal;%0A%0Aimport java.io.Serializable;%0Aimport java.time.Instant;%0A%0Aimport static com.google.common.base.Preconditions.checkNotNull
+time.temporal.TimestampTemporal;%0A%0Aimport java.time.Instant
 ;%0A%0A/
@@ -1858,82 +1858,47 @@
     
-checkNotNull(timestamp);%0A        return InstantConverter.INSTANCE.reverse(
+return TimestampTemporal.from(timestamp
 )%0A  
@@ -1931,34 +1931,19 @@
     
-        .convert(timestamp
+.toInstant(
 );%0A 
@@ -4119,78 +4119,44 @@
     
-checkNotNull(str);%0A        return Stringifiers.forTimestamp()%0A        
+return TimestampTemporal.parse(str)%0A
     
@@ -4172,21 +4172,8 @@
     
-  .reverse()%0A
     
@@ -4187,32 +4187,21 @@
     
-            .convert(str
+.toTimestamp(
 );%0A 
@@ -4375,28 +4375,45 @@
         
-checkNotNull
+return TimestampTemporal.from
 (instant
@@ -4409,25 +4409,24 @@
 rom(instant)
-;
 %0A        ret
@@ -4426,56 +4426,45 @@
     
-return InstantConverter.INSTANCE.convert(instant
+                        .toTimestamp(
 );%0A 
@@ -4650,1166 +4650,38 @@
 urn 
-InstantConverter.INSTANCE;%0A    %7D%0A%0A    /**%0A     * Converts %7B@code Timestamp%7D to %7B@code Instant%7D.%0A     */%0A    @Deprecated%0A    private static final class InstantConverter extends Converter%3CInstant, Timestamp%3E%0A            implements Serializable %7B%0A%0A        private static final long serialVersionUID = 0L;%0A        private static final InstantConverter INSTANCE = new InstantConverter();%0A%0A        @Override%0A        protected Timestamp doForward(Instant value) %7B%0A            checkNotNull(value);%0A            Timestamp result = Timestamp%0A                    .newBuilder()%0A                    .setSeconds(value.getEpochSecond())%0A                    .setNanos(value.getNano())%0A                    .build();%0A            return result;%0A        %7D%0A%0A        @Override%0A        protected Instant doBackward(Timestamp value) %7B%0A            checkNotNull(value);%0A            Instant result = Instant.ofEpochSecond(value.getSeconds(), value.getNanos());%0A            return result;%0A        %7D%0A%0A        @Override%0A        public String toString() %7B%0A            return %22Timestamps2.converter()%22;%0A        %7D%0A%0A        private Object readResolve() %7B%0A            return INSTANCE;%0A        %7D
+TimestampTemporal.converter();
 %0A   

Use methods of `TimestampTemporal` in `Timestamps2`.