/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * 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 android.location;

import android.annotation.FloatRange;
import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;

/**
 * A class containing a GPS clock timestamp.
 *
 * <p>It represents a measurement of the GPS receiver's clock.
 */
public final class GnssClock implements Parcelable {
    // The following enumerations must be in sync with the values declared in gps.h

    private static final int HAS_NO_FLAGS = 0;
    private static final int HAS_LEAP_SECOND = (1<<0);
    private static final int HAS_TIME_UNCERTAINTY = (1<<1);
    private static final int HAS_FULL_BIAS = (1<<2);
    private static final int HAS_BIAS = (1<<3);
    private static final int HAS_BIAS_UNCERTAINTY = (1<<4);
    private static final int HAS_DRIFT = (1<<5);
    private static final int HAS_DRIFT_UNCERTAINTY = (1<<6);
    private static final int HAS_ELAPSED_REALTIME_NANOS = (1 << 7);
    private static final int HAS_ELAPSED_REALTIME_UNCERTAINTY_NANOS = (1 << 8);

    // End enumerations in sync with gps.h

    private int mFlags;
    private int mLeapSecond;
    private long mTimeNanos;
    private double mTimeUncertaintyNanos;
    private long mFullBiasNanos;
    private double mBiasNanos;
    private double mBiasUncertaintyNanos;
    private double mDriftNanosPerSecond;
    private double mDriftUncertaintyNanosPerSecond;
    private int mHardwareClockDiscontinuityCount;
    private long mElapsedRealtimeNanos;
    private double mElapsedRealtimeUncertaintyNanos;

    /**
     * @hide
     */
    @TestApi
    public GnssClock() {
        initialize();
    }

    /**
     * Sets all contents to the values stored in the provided object.
     * @hide
     */
    @TestApi
    public void set(GnssClock clock) {
        mFlags = clock.mFlags;
        mLeapSecond = clock.mLeapSecond;
        mTimeNanos = clock.mTimeNanos;
        mTimeUncertaintyNanos = clock.mTimeUncertaintyNanos;
        mFullBiasNanos = clock.mFullBiasNanos;
        mBiasNanos = clock.mBiasNanos;
        mBiasUncertaintyNanos = clock.mBiasUncertaintyNanos;
        mDriftNanosPerSecond = clock.mDriftNanosPerSecond;
        mDriftUncertaintyNanosPerSecond = clock.mDriftUncertaintyNanosPerSecond;
        mHardwareClockDiscontinuityCount = clock.mHardwareClockDiscontinuityCount;
        mElapsedRealtimeNanos = clock.mElapsedRealtimeNanos;
        mElapsedRealtimeUncertaintyNanos = clock.mElapsedRealtimeUncertaintyNanos;
    }

    /**
     * Resets all the contents to its original state.
     * @hide
     */
    @TestApi
    public void reset() {
        initialize();
    }

    /**
     * Returns {@code true} if {@link #getLeapSecond()} is available, {@code false} otherwise.
     */
    public boolean hasLeapSecond() {
        return isFlagSet(HAS_LEAP_SECOND);
    }

    /**
     * Gets the leap second associated with the clock's time.
     *
     * <p>The sign of the value is defined by the following equation:
     * <pre>
     *     UtcTimeNanos = TimeNanos - (FullBiasNanos + BiasNanos) - LeapSecond * 1,000,000,000</pre>
     *
     * <p>The value is only available if {@link #hasLeapSecond()} is {@code true}.
     */
    public int getLeapSecond() {
        return mLeapSecond;
    }

    /**
     * Sets the leap second associated with the clock's time.
     * @hide
     */
    @TestApi
    public void setLeapSecond(int leapSecond) {
        setFlag(HAS_LEAP_SECOND);
        mLeapSecond = leapSecond;
    }

    /**
     * Resets the leap second associated with the clock's time.
     * @hide
     */
    @TestApi
    public void resetLeapSecond() {
        resetFlag(HAS_LEAP_SECOND);
        mLeapSecond = Integer.MIN_VALUE;
    }

    /**
     * Gets the GNSS receiver internal hardware clock value in nanoseconds.
     *
     * <p>This value is expected to be monotonically increasing while the hardware clock remains
     * powered on. For the case of a hardware clock that is not continuously on, see the
     * {@link #getHardwareClockDiscontinuityCount} field. The GPS time can be derived by subtracting
     * the sum of {@link #getFullBiasNanos()} and {@link #getBiasNanos()} (when they are available)
     * from this value. Sub-nanosecond accuracy can be provided by means of {@link #getBiasNanos()}.
     *
     * <p>The error estimate for this value (if applicable) is {@link #getTimeUncertaintyNanos()}.
     */
    public long getTimeNanos() {
        return mTimeNanos;
    }

    /**
     * Sets the GNSS receiver internal clock in nanoseconds.
     * @hide
     */
    @TestApi
    public void setTimeNanos(long timeNanos) {
        mTimeNanos = timeNanos;
    }

    /**
     * Returns {@code true} if {@link #getTimeUncertaintyNanos()} is available, {@code false}
     * otherwise.
     */
    public boolean hasTimeUncertaintyNanos() {
        return isFlagSet(HAS_TIME_UNCERTAINTY);
    }

    /**
     * Gets the clock's time Uncertainty (1-Sigma) in nanoseconds.
     *
     * <p>The uncertainty is represented as an absolute (single sided) value.
     *
     * <p>The value is only available if {@link #hasTimeUncertaintyNanos()} is {@code true}.
     *
     * <p>This value is often effectively zero (it is the reference clock by which all other times
     * and time uncertainties are measured), and thus this field may often be 0, or not provided.
     */
    @FloatRange(from = 0.0f)
    public double getTimeUncertaintyNanos() {
        return mTimeUncertaintyNanos;
    }

    /**
     * Sets the clock's Time Uncertainty (1-Sigma) in nanoseconds.
     * @hide
     */
    @TestApi
    public void setTimeUncertaintyNanos(@FloatRange(from = 0.0f) double timeUncertaintyNanos) {
        setFlag(HAS_TIME_UNCERTAINTY);
        mTimeUncertaintyNanos = timeUncertaintyNanos;
    }

    /**
     * Resets the clock's Time Uncertainty (1-Sigma) in nanoseconds.
     * @hide
     */
    @TestApi
    public void resetTimeUncertaintyNanos() {
        resetFlag(HAS_TIME_UNCERTAINTY);
        mTimeUncertaintyNanos = Double.NaN;
    }

    /**
     * Returns {@code true} if {@link #getFullBiasNanos()} is available, {@code false} otherwise.
     */
    public boolean hasFullBiasNanos() {
        return isFlagSet(HAS_FULL_BIAS);
    }

    /**
     * Gets the difference between hardware clock ({@link #getTimeNanos()}) inside GPS receiver and
     * the true GPS time since 0000Z, January 6, 1980, in nanoseconds.
     *
     * <p>This value is available if the receiver has estimated GPS time. If the computed time is
     * for a non-GPS constellation, the time offset of that constellation to GPS has to be applied
     * to fill this value. The value is only available if {@link #hasFullBiasNanos()} is
     * {@code true}.
     *
     * <p>The error estimate for the sum of this field and {@link #getBiasNanos} is
     * {@link #getBiasUncertaintyNanos()}.
     *
     * <p>The sign of the value is defined by the following equation:
     *
     * <pre>
     *     local estimate of GPS time = TimeNanos - (FullBiasNanos + BiasNanos)</pre>
     */
    public long getFullBiasNanos() {
        return mFullBiasNanos;
    }

    /**
     * Sets the full bias in nanoseconds.
     * @hide
     */
    @TestApi
    public void setFullBiasNanos(long value) {
        setFlag(HAS_FULL_BIAS);
        mFullBiasNanos = value;
    }

    /**
     * Resets the full bias in nanoseconds.
     * @hide
     */
    @TestApi
    public void resetFullBiasNanos() {
        resetFlag(HAS_FULL_BIAS);
        mFullBiasNanos = Long.MIN_VALUE;
    }

    /**
     * Returns {@code true} if {@link #getBiasNanos()} is available, {@code false} otherwise.
     */
    public boolean hasBiasNanos() {
        return isFlagSet(HAS_BIAS);
    }

    /**
     * Gets the clock's sub-nanosecond bias.
     *
     * <p>See the description of how this field is part of converting from hardware clock time, to
     * GPS time, in {@link #getFullBiasNanos()}.
     *
     * <p>The error estimate for the sum of this field and {@link #getFullBiasNanos} is
     * {@link #getBiasUncertaintyNanos()}.
     *
     * <p>The value is only available if {@link #hasBiasNanos()} is {@code true}.
     */
    public double getBiasNanos() {
        return mBiasNanos;
    }

    /**
     * Sets the sub-nanosecond bias.
     * @hide
     */
    @TestApi
    public void setBiasNanos(double biasNanos) {
        setFlag(HAS_BIAS);
        mBiasNanos = biasNanos;
    }

    /**
     * Resets the clock's Bias in nanoseconds.
     * @hide
     */
    @TestApi
    public void resetBiasNanos() {
        resetFlag(HAS_BIAS);
        mBiasNanos = Double.NaN;
    }

    /**
     * Returns {@code true} if {@link #getBiasUncertaintyNanos()} is available, {@code false}
     * otherwise.
     */
    public boolean hasBiasUncertaintyNanos() {
        return isFlagSet(HAS_BIAS_UNCERTAINTY);
    }

    /**
     * Gets the clock's Bias Uncertainty (1-Sigma) in nanoseconds.
     *
     * <p>See the description of how this field provides the error estimate in the conversion from
     * hardware clock time, to GPS time, in {@link #getFullBiasNanos()}.
     *
     * <p>The value is only available if {@link #hasBiasUncertaintyNanos()} is {@code true}.
     */
    @FloatRange(from = 0.0f)
    public double getBiasUncertaintyNanos() {
        return mBiasUncertaintyNanos;
    }

    /**
     * Sets the clock's Bias Uncertainty (1-Sigma) in nanoseconds.
     * @hide
     */
    @TestApi
    public void setBiasUncertaintyNanos(@FloatRange(from = 0.0f) double biasUncertaintyNanos) {
        setFlag(HAS_BIAS_UNCERTAINTY);
        mBiasUncertaintyNanos = biasUncertaintyNanos;
    }

    /**
     * Resets the clock's Bias Uncertainty (1-Sigma) in nanoseconds.
     * @hide
     */
    @TestApi
    public void resetBiasUncertaintyNanos() {
        resetFlag(HAS_BIAS_UNCERTAINTY);
        mBiasUncertaintyNanos = Double.NaN;
    }

    /**
     * Returns {@code true} if {@link #getDriftNanosPerSecond()} is available, {@code false}
     * otherwise.
     */
    public boolean hasDriftNanosPerSecond() {
        return isFlagSet(HAS_DRIFT);
    }

    /**
     * Gets the clock's Drift in nanoseconds per second.
     *
     * <p>This value is the instantaneous time-derivative of the value provided by
     * {@link #getBiasNanos()}.
     *
     * <p>A positive value indicates that the frequency is higher than the nominal (e.g. GPS master
     * clock) frequency. The error estimate for this reported drift is
     * {@link #getDriftUncertaintyNanosPerSecond()}.
     *
     * <p>The value is only available if {@link #hasDriftNanosPerSecond()} is {@code true}.
     */
    public double getDriftNanosPerSecond() {
        return mDriftNanosPerSecond;
    }

    /**
     * Sets the clock's Drift in nanoseconds per second.
     * @hide
     */
    @TestApi
    public void setDriftNanosPerSecond(double driftNanosPerSecond) {
        setFlag(HAS_DRIFT);
        mDriftNanosPerSecond = driftNanosPerSecond;
    }

    /**
     * Resets the clock's Drift in nanoseconds per second.
     * @hide
     */
    @TestApi
    public void resetDriftNanosPerSecond() {
        resetFlag(HAS_DRIFT);
        mDriftNanosPerSecond = Double.NaN;
    }

    /**
     * Returns {@code true} if {@link #getDriftUncertaintyNanosPerSecond()} is available,
     * {@code false} otherwise.
     */
    public boolean hasDriftUncertaintyNanosPerSecond() {
        return isFlagSet(HAS_DRIFT_UNCERTAINTY);
    }

    /**
     * Gets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
     *
     * <p>The value is only available if {@link #hasDriftUncertaintyNanosPerSecond()} is
     * {@code true}.
     */
    @FloatRange(from = 0.0f)
    public double getDriftUncertaintyNanosPerSecond() {
        return mDriftUncertaintyNanosPerSecond;
    }

    /**
     * Sets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
     * @hide
     */
    @TestApi
    public void setDriftUncertaintyNanosPerSecond(
            @FloatRange(from = 0.0f) double driftUncertaintyNanosPerSecond) {
        setFlag(HAS_DRIFT_UNCERTAINTY);
        mDriftUncertaintyNanosPerSecond = driftUncertaintyNanosPerSecond;
    }

    /**
     * Resets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
     * @hide
     */
    @TestApi
    public void resetDriftUncertaintyNanosPerSecond() {
        resetFlag(HAS_DRIFT_UNCERTAINTY);
        mDriftUncertaintyNanosPerSecond = Double.NaN;
    }

    /**
     * Returns {@code true} if {@link #getElapsedRealtimeNanos()} is available, {@code false}
     * otherwise.
     */
    public boolean hasElapsedRealtimeNanos() {
        return isFlagSet(HAS_ELAPSED_REALTIME_NANOS);
    }

    /**
     * Returns the elapsed real-time of this clock since system boot, in nanoseconds.
     *
     * <p>The value is only available if {@link #hasElapsedRealtimeNanos()} is
     * {@code true}.
     */
    public long getElapsedRealtimeNanos() {
        return mElapsedRealtimeNanos;
    }

    /**
     * Sets the elapsed real-time of this clock since system boot, in nanoseconds.
     * @hide
     */
    @TestApi
    public void setElapsedRealtimeNanos(long elapsedRealtimeNanos) {
        setFlag(HAS_ELAPSED_REALTIME_NANOS);
        mElapsedRealtimeNanos = elapsedRealtimeNanos;
    }

    /**
     * Resets the elapsed real-time of this clock since system boot, in nanoseconds.
     * @hide
     */
    @TestApi
    public void resetElapsedRealtimeNanos() {
        resetFlag(HAS_ELAPSED_REALTIME_NANOS);
        mElapsedRealtimeNanos = 0;
    }

    /**
     * Returns {@code true} if {@link #getElapsedRealtimeUncertaintyNanos()} is available, {@code
     * false} otherwise.
     */
    public boolean hasElapsedRealtimeUncertaintyNanos() {
        return isFlagSet(HAS_ELAPSED_REALTIME_UNCERTAINTY_NANOS);
    }

    /**
     * Gets the estimate of the relative precision of the alignment of the
     * {@link #getElapsedRealtimeNanos()} timestamp, with the reported measurements in
     * nanoseconds (68% confidence).
     *
     * <p>The value is only available if {@link #hasElapsedRealtimeUncertaintyNanos()} is
     * {@code true}.
     */
    @FloatRange(from = 0.0f)
    public double getElapsedRealtimeUncertaintyNanos() {
        return mElapsedRealtimeUncertaintyNanos;
    }

    /**
     * Sets the estimate of the relative precision of the alignment of the
     * {@link #getElapsedRealtimeNanos()} timestamp, with the reported measurements in
     * nanoseconds (68% confidence).
     * @hide
     */
    @TestApi
    public void setElapsedRealtimeUncertaintyNanos(
            @FloatRange(from = 0.0f) double elapsedRealtimeUncertaintyNanos) {
        setFlag(HAS_ELAPSED_REALTIME_UNCERTAINTY_NANOS);
        mElapsedRealtimeUncertaintyNanos = elapsedRealtimeUncertaintyNanos;
    }

    /**
     * Resets the estimate of the relative precision of the alignment of the
     * {@link #getElapsedRealtimeNanos()} timestamp, with the reported measurements in
     * nanoseconds (68% confidence).
     * @hide
     */
    @TestApi
    public void resetElapsedRealtimeUncertaintyNanos() {
        resetFlag(HAS_ELAPSED_REALTIME_UNCERTAINTY_NANOS);
        mElapsedRealtimeUncertaintyNanos = Double.NaN;
    }

    /**
     * Gets count of hardware clock discontinuities.
     *
     * <p>When this value stays the same, vs. a value in a previously reported {@link GnssClock}, it
     * can be safely assumed that the {@code TimeNanos} value has been derived from a clock that has
     * been running continuously - e.g. a single continuously powered crystal oscillator, and thus
     * the {@code (FullBiasNanos + BiasNanos)} offset can be modelled with traditional clock bias
     * &amp; drift models.
     *
     * <p>Each time this value changes, vs. the value in a previously reported {@link GnssClock},
     * that suggests the hardware clock may have experienced a discontinuity (e.g. a power cycle or
     * other anomaly), so that any assumptions about modelling a smoothly changing
     * {@code (FullBiasNanos + BiasNanos)} offset, and a smoothly growing {@code (TimeNanos)}
     * between this and the previously reported {@code GnssClock}, should be reset.
     */
    public int getHardwareClockDiscontinuityCount() {
        return mHardwareClockDiscontinuityCount;
    }

    /**
     * Sets count of last hardware clock discontinuity.
     * @hide
     */
    @TestApi
    public void setHardwareClockDiscontinuityCount(int value) {
        mHardwareClockDiscontinuityCount = value;
    }

    public static final @android.annotation.NonNull Creator<GnssClock> CREATOR = new Creator<GnssClock>() {
        @Override
        public GnssClock createFromParcel(Parcel parcel) {
            GnssClock gpsClock = new GnssClock();

            gpsClock.mFlags = parcel.readInt();
            gpsClock.mLeapSecond = parcel.readInt();
            gpsClock.mTimeNanos = parcel.readLong();
            gpsClock.mTimeUncertaintyNanos = parcel.readDouble();
            gpsClock.mFullBiasNanos = parcel.readLong();
            gpsClock.mBiasNanos = parcel.readDouble();
            gpsClock.mBiasUncertaintyNanos = parcel.readDouble();
            gpsClock.mDriftNanosPerSecond = parcel.readDouble();
            gpsClock.mDriftUncertaintyNanosPerSecond = parcel.readDouble();
            gpsClock.mHardwareClockDiscontinuityCount = parcel.readInt();
            gpsClock.mElapsedRealtimeNanos = parcel.readLong();
            gpsClock.mElapsedRealtimeUncertaintyNanos = parcel.readDouble();

            return gpsClock;
        }

        @Override
        public GnssClock[] newArray(int size) {
            return new GnssClock[size];
        }
    };

    @Override
    public void writeToParcel(Parcel parcel, int flags) {
        parcel.writeInt(mFlags);
        parcel.writeInt(mLeapSecond);
        parcel.writeLong(mTimeNanos);
        parcel.writeDouble(mTimeUncertaintyNanos);
        parcel.writeLong(mFullBiasNanos);
        parcel.writeDouble(mBiasNanos);
        parcel.writeDouble(mBiasUncertaintyNanos);
        parcel.writeDouble(mDriftNanosPerSecond);
        parcel.writeDouble(mDriftUncertaintyNanosPerSecond);
        parcel.writeInt(mHardwareClockDiscontinuityCount);
        parcel.writeLong(mElapsedRealtimeNanos);
        parcel.writeDouble(mElapsedRealtimeUncertaintyNanos);
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public String toString() {
        final String format = "   %-15s = %s\n";
        final String formatWithUncertainty = "   %-15s = %-25s   %-26s = %s\n";
        StringBuilder builder = new StringBuilder("GnssClock:\n");

        builder.append(String.format(format, "LeapSecond", hasLeapSecond() ? mLeapSecond : null));

        builder.append(String.format(
                formatWithUncertainty,
                "TimeNanos",
                mTimeNanos,
                "TimeUncertaintyNanos",
                hasTimeUncertaintyNanos() ? mTimeUncertaintyNanos : null));

        builder.append(String.format(
                format,
                "FullBiasNanos",
                hasFullBiasNanos() ? mFullBiasNanos : null));

        builder.append(String.format(
                formatWithUncertainty,
                "BiasNanos",
                hasBiasNanos() ? mBiasNanos : null,
                "BiasUncertaintyNanos",
                hasBiasUncertaintyNanos() ? mBiasUncertaintyNanos : null));

        builder.append(String.format(
                formatWithUncertainty,
                "DriftNanosPerSecond",
                hasDriftNanosPerSecond() ? mDriftNanosPerSecond : null,
                "DriftUncertaintyNanosPerSecond",
                hasDriftUncertaintyNanosPerSecond() ? mDriftUncertaintyNanosPerSecond : null));

        builder.append(String.format(
                format,
                "HardwareClockDiscontinuityCount",
                mHardwareClockDiscontinuityCount));

        builder.append(String.format(
                format,
                "ElapsedRealtimeNanos",
                hasElapsedRealtimeNanos() ? mElapsedRealtimeNanos : null));

        builder.append(String.format(
                format,
                "ElapsedRealtimeUncertaintyNanos",
                hasElapsedRealtimeUncertaintyNanos() ? mElapsedRealtimeUncertaintyNanos : null));

        return builder.toString();
    }

    private void initialize() {
        mFlags = HAS_NO_FLAGS;
        resetLeapSecond();
        setTimeNanos(Long.MIN_VALUE);
        resetTimeUncertaintyNanos();
        resetFullBiasNanos();
        resetBiasNanos();
        resetBiasUncertaintyNanos();
        resetDriftNanosPerSecond();
        resetDriftUncertaintyNanosPerSecond();
        setHardwareClockDiscontinuityCount(Integer.MIN_VALUE);
        resetElapsedRealtimeNanos();
        resetElapsedRealtimeUncertaintyNanos();
    }

    private void setFlag(int flag) {
        mFlags |= flag;
    }

    private void resetFlag(int flag) {
        mFlags &= ~flag;
    }

    private boolean isFlagSet(int flag) {
        return (mFlags & flag) == flag;
    }
}
