/*
 * 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.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;

/**
 * A class containing a GPS clock timestamp.
 * It represents a measurement of the GPS receiver's clock.
 *
 * @hide
 */
@SystemApi
public class GpsClock implements Parcelable {

    // The following enumerations must be in sync with the values declared in gps.h

    /**
     * The type of the time stored is not available or it is unknown.
     */
    public static final byte TYPE_UNKNOWN = 0;

    /**
     * The source of the time value reported by this class is the 'Local Hardware Clock'.
     */
    public static final byte TYPE_LOCAL_HW_TIME = 1;

    /**
     * The source of the time value reported by this class is the 'GPS time' derived from
     * satellites (epoch = Jan 6, 1980).
     */
    public static final byte TYPE_GPS_TIME = 2;

    private static final short HAS_NO_FLAGS = 0;
    private static final short HAS_LEAP_SECOND = (1<<0);
    private static final short HAS_TIME_UNCERTAINTY = (1<<1);
    private static final short HAS_FULL_BIAS = (1<<2);
    private static final short HAS_BIAS = (1<<3);
    private static final short HAS_BIAS_UNCERTAINTY = (1<<4);
    private static final short HAS_DRIFT = (1<<5);
    private static final short HAS_DRIFT_UNCERTAINTY = (1<<6);

    // End enumerations in sync with gps.h

    private short mFlags;
    private short mLeapSecond;
    private byte mType;
    private long mTimeInNs;
    private double mTimeUncertaintyInNs;
    private long mFullBiasInNs;
    private double mBiasInNs;
    private double mBiasUncertaintyInNs;
    private double mDriftInNsPerSec;
    private double mDriftUncertaintyInNsPerSec;

    GpsClock() {
        initialize();
    }

    /**
     * Sets all contents to the values stored in the provided object.
     */
    public void set(GpsClock clock) {
        mFlags = clock.mFlags;
        mLeapSecond = clock.mLeapSecond;
        mType = clock.mType;
        mTimeInNs = clock.mTimeInNs;
        mTimeUncertaintyInNs = clock.mTimeUncertaintyInNs;
        mFullBiasInNs = clock.mFullBiasInNs;
        mBiasInNs = clock.mBiasInNs;
        mBiasUncertaintyInNs = clock.mBiasUncertaintyInNs;
        mDriftInNsPerSec = clock.mDriftInNsPerSec;
        mDriftUncertaintyInNsPerSec = clock.mDriftUncertaintyInNsPerSec;
    }

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

    /**
     * Gets the type of time reported by {@link #getTimeInNs()}.
     */
    public byte getType() {
        return mType;
    }

    /**
     * Sets the type of time reported.
     */
    public void setType(byte value) {
        mType = value;
    }

    /**
     * Gets a string representation of the 'type'.
     * For internal and logging use only.
     */
    private String getTypeString() {
        switch (mType) {
            case TYPE_UNKNOWN:
                return "Unknown";
            case TYPE_GPS_TIME:
                return "GpsTime";
            case TYPE_LOCAL_HW_TIME:
                return "LocalHwClock";
            default:
                return "<Invalid:" + mType + ">";
        }
    }

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

    /**
     * Gets the leap second associated with the clock's time.
     * The sign of the value is defined by the following equation:
     *      utc_time_ns = time_ns + (full_bias_ns + bias_ns) - leap_second * 1,000,000,000
     *
     * The value is only available if {@link #hasLeapSecond()} is true.
     */
    public short getLeapSecond() {
        return mLeapSecond;
    }

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

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

    /**
     * Gets the GPS receiver internal clock value in nanoseconds.
     * This can be either the 'local hardware clock' value ({@link #TYPE_LOCAL_HW_TIME}), or the
     * current GPS time derived inside GPS receiver ({@link #TYPE_GPS_TIME}).
     * {@link #getType()} defines the time reported.
     *
     * For 'local hardware clock' this value is expected to be monotonically increasing during the
     * reporting session. The real GPS time can be derived by compensating
     * {@link #getFullBiasInNs()} (when it is available) from this value.
     *
     * For 'GPS time' this value is expected to be the best estimation of current GPS time that GPS
     * receiver can achieve. {@link #getTimeUncertaintyInNs()} should be available when GPS time is
     * specified.
     *
     * Sub-nanosecond accuracy can be provided by means of {@link #getBiasInNs()}.
     * The reported time includes {@link #getTimeUncertaintyInNs()}.
     */
    public long getTimeInNs() {
        return mTimeInNs;
    }

    /**
     * Sets the GPS receiver internal clock in nanoseconds.
     */
    public void setTimeInNs(long timeInNs) {
        mTimeInNs = timeInNs;
    }

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

    /**
     * Gets the clock's time Uncertainty (1-Sigma) in nanoseconds.
     * The uncertainty is represented as an absolute (single sided) value.
     *
     * The value is only available if {@link #hasTimeUncertaintyInNs()} is true.
     */
    public double getTimeUncertaintyInNs() {
        return mTimeUncertaintyInNs;
    }

    /**
     * Sets the clock's Time Uncertainty (1-Sigma) in nanoseconds.
     */
    public void setTimeUncertaintyInNs(double timeUncertaintyInNs) {
        setFlag(HAS_TIME_UNCERTAINTY);
        mTimeUncertaintyInNs = timeUncertaintyInNs;
    }

    /**
     * Resets the clock's Time Uncertainty (1-Sigma) in nanoseconds.
     */
    public void resetTimeUncertaintyInNs() {
        resetFlag(HAS_TIME_UNCERTAINTY);
        mTimeUncertaintyInNs = Double.NaN;
    }

    /**
     * Returns true if {@link @getFullBiasInNs()} is available, false otherwise.
     */
    public boolean hasFullBiasInNs() {
        return isFlagSet(HAS_FULL_BIAS);
    }

    /**
     * Gets the difference between hardware clock ({@link #getTimeInNs()}) inside GPS receiver and
     * the true GPS time since 0000Z, January 6, 1980, in nanoseconds.
     *
     * This value is available if {@link #TYPE_LOCAL_HW_TIME} is set, and GPS receiver has solved
     * the clock for GPS time.
     * {@link #getBiasUncertaintyInNs()} should be used for quality check.
     *
     * The sign of the value is defined by the following equation:
     *      true time (GPS time) = time_ns + (full_bias_ns + bias_ns)
     *
     * The reported full bias includes {@link #getBiasUncertaintyInNs()}.
     * The value is onl available if {@link #hasFullBiasInNs()} is true.
     */
    public long getFullBiasInNs() {
        return mFullBiasInNs;
    }

    /**
     * Sets the full bias in nanoseconds.
     */
    public void setFullBiasInNs(long value) {
        setFlag(HAS_FULL_BIAS);
        mFullBiasInNs = value;
    }

    /**
     * Resets the full bias in nanoseconds.
     */
    public void resetFullBiasInNs() {
        resetFlag(HAS_FULL_BIAS);
        mFullBiasInNs = Long.MIN_VALUE;
    }

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

    /**
     * Gets the clock's sub-nanosecond bias.
     * The reported bias includes {@link #getBiasUncertaintyInNs()}.
     *
     * The value is only available if {@link #hasBiasInNs()} is true.
     */
    public double getBiasInNs() {
        return mBiasInNs;
    }

    /**
     * Sets the sub-nanosecond bias.
     */
    public void setBiasInNs(double biasInNs) {
        setFlag(HAS_BIAS);
        mBiasInNs = biasInNs;
    }

    /**
     * Resets the clock's Bias in nanoseconds.
     */
    public void resetBiasInNs() {
        resetFlag(HAS_BIAS);
        mBiasInNs = Double.NaN;
    }

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

    /**
     * Gets the clock's Bias Uncertainty (1-Sigma) in nanoseconds.
     *
     * The value is only available if {@link #hasBiasUncertaintyInNs()} is true.
     */
    public double getBiasUncertaintyInNs() {
        return mBiasUncertaintyInNs;
    }

    /**
     * Sets the clock's Bias Uncertainty (1-Sigma) in nanoseconds.
     */
    public void setBiasUncertaintyInNs(double biasUncertaintyInNs) {
        setFlag(HAS_BIAS_UNCERTAINTY);
        mBiasUncertaintyInNs = biasUncertaintyInNs;
    }

    /**
     * Resets the clock's Bias Uncertainty (1-Sigma) in nanoseconds.
     */
    public void resetBiasUncertaintyInNs() {
        resetFlag(HAS_BIAS_UNCERTAINTY);
        mBiasUncertaintyInNs = Double.NaN;
    }

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

    /**
     * Gets the clock's Drift in nanoseconds per second.
     * A positive value indicates that the frequency is higher than the nominal frequency.
     * The reported drift includes {@link #getDriftUncertaintyInNsPerSec()}.
     *
     * The value is only available if {@link #hasDriftInNsPerSec()} is true.
     */
    public double getDriftInNsPerSec() {
        return mDriftInNsPerSec;
    }

    /**
     * Sets the clock's Drift in nanoseconds per second.
     */
    public void setDriftInNsPerSec(double driftInNsPerSec) {
        setFlag(HAS_DRIFT);
        mDriftInNsPerSec = driftInNsPerSec;
    }

    /**
     * Resets the clock's Drift in nanoseconds per second.
     */
    public void resetDriftInNsPerSec() {
        resetFlag(HAS_DRIFT);
        mDriftInNsPerSec = Double.NaN;
    }

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

    /**
     * Gets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
     *
     * The value is only available if {@link #hasDriftUncertaintyInNsPerSec()} is true.
     */
    public double getDriftUncertaintyInNsPerSec() {
        return mDriftUncertaintyInNsPerSec;
    }

    /**
     * Sets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
     */
    public void setDriftUncertaintyInNsPerSec(double driftUncertaintyInNsPerSec) {
        setFlag(HAS_DRIFT_UNCERTAINTY);
        mDriftUncertaintyInNsPerSec = driftUncertaintyInNsPerSec;
    }

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

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

            gpsClock.mFlags = (short) parcel.readInt();
            gpsClock.mLeapSecond = (short) parcel.readInt();
            gpsClock.mType = parcel.readByte();
            gpsClock.mTimeInNs = parcel.readLong();
            gpsClock.mTimeUncertaintyInNs = parcel.readDouble();
            gpsClock.mFullBiasInNs = parcel.readLong();
            gpsClock.mBiasInNs = parcel.readDouble();
            gpsClock.mBiasUncertaintyInNs = parcel.readDouble();
            gpsClock.mDriftInNsPerSec = parcel.readDouble();
            gpsClock.mDriftUncertaintyInNsPerSec = parcel.readDouble();

            return gpsClock;
        }

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

    public void writeToParcel(Parcel parcel, int flags) {
        parcel.writeInt(mFlags);
        parcel.writeInt(mLeapSecond);
        parcel.writeByte(mType);
        parcel.writeLong(mTimeInNs);
        parcel.writeDouble(mTimeUncertaintyInNs);
        parcel.writeLong(mFullBiasInNs);
        parcel.writeDouble(mBiasInNs);
        parcel.writeDouble(mBiasUncertaintyInNs);
        parcel.writeDouble(mDriftInNsPerSec);
        parcel.writeDouble(mDriftUncertaintyInNsPerSec);
    }

    @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("GpsClock:\n");

        builder.append(String.format(format, "Type", getTypeString()));

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

        builder.append(String.format(
                formatWithUncertainty,
                "TimeInNs",
                mTimeInNs,
                "TimeUncertaintyInNs",
                hasTimeUncertaintyInNs() ? mTimeUncertaintyInNs : null));

        builder.append(String.format(
                format,
                "FullBiasInNs",
                hasFullBiasInNs() ? mFullBiasInNs : null));

        builder.append(String.format(
                formatWithUncertainty,
                "BiasInNs",
                hasBiasInNs() ? mBiasInNs : null,
                "BiasUncertaintyInNs",
                hasBiasUncertaintyInNs() ? mBiasUncertaintyInNs : null));

        builder.append(String.format(
                formatWithUncertainty,
                "DriftInNsPerSec",
                hasDriftInNsPerSec() ? mDriftInNsPerSec : null,
                "DriftUncertaintyInNsPerSec",
                hasDriftUncertaintyInNsPerSec() ? mDriftUncertaintyInNsPerSec : null));

        return builder.toString();
    }

    private void initialize() {
        mFlags = HAS_NO_FLAGS;
        resetLeapSecond();
        setType(TYPE_UNKNOWN);
        setTimeInNs(Long.MIN_VALUE);
        resetTimeUncertaintyInNs();
        resetFullBiasInNs();
        resetBiasInNs();
        resetBiasUncertaintyInNs();
        resetDriftInNsPerSec();
        resetDriftUncertaintyInNsPerSec();
    }

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

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

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