/*
 * Copyright (C) 2017 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.app.timezone;

import static android.app.timezone.Utils.validateConditionalNull;
import static android.app.timezone.Utils.validateNotNull;
import static android.app.timezone.Utils.validateRulesVersion;

import android.annotation.IntDef;
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * Description of the state of time zone rules on a device.
 *
 * <p>The following properties are included:
 * <dl>
 *     <dt>baseRulesVersion</dt>
 *     <dd>the IANA rules version that shipped with the OS. Always present. e.g. "2017a".</dd>
 *     <dt>distroFormatVersionSupported</dt>
 *     <dd>the distro format version supported by this device. Always present.</dd>
 *     <dt>operationInProgress</dt>
 *     <dd>{@code true} if there is an install / uninstall operation currently happening.</dd>
 *     <dt>stagedOperationType</dt>
 *     <dd>one of {@link #STAGED_OPERATION_UNKNOWN}, {@link #STAGED_OPERATION_NONE},
 *     {@link #STAGED_OPERATION_UNINSTALL} and {@link #STAGED_OPERATION_INSTALL} indicating whether
 *     there is a currently staged time zone distro operation. {@link #STAGED_OPERATION_UNKNOWN} is
 *     used when {@link #isOperationInProgress()} is {@code true}. Staged operations currently
 *     require a reboot to become active.</dd>
 *     <dt>stagedDistroRulesVersion</dt>
 *     <dd>[present if distroStagedState == STAGED_STATE_INSTALL], the rules version of the distro
 *     currently staged for installation.</dd>
 *     <dt>distroStatus</dt>
 *     <dd>{@link #DISTRO_STATUS_INSTALLED} if there is a time zone distro installed and active,
 *     {@link #DISTRO_STATUS_NONE} if there is no active installed distro.
 *     {@link #DISTRO_STATUS_UNKNOWN} is used when {@link #isOperationInProgress()} is {@code true}.
 *     </dd>
 *     <dt>installedDistroRulesVersion</dt>
 *     <dd>[present if distroStatus == {@link #DISTRO_STATUS_INSTALLED}], the rules version of the
 *     installed and active distro.</dd>
 * </dl>
 *
 * @hide
 */
public final class RulesState implements Parcelable {

    @Retention(RetentionPolicy.SOURCE)
    @IntDef(prefix = { "STAGED_OPERATION_" }, value = {
            STAGED_OPERATION_UNKNOWN,
            STAGED_OPERATION_NONE,
            STAGED_OPERATION_UNINSTALL,
            STAGED_OPERATION_INSTALL
    })
    private @interface StagedOperationType {}

    /** Staged state could not be determined. */
    public static final int STAGED_OPERATION_UNKNOWN = 0;
    /** Nothing is staged. */
    public static final int STAGED_OPERATION_NONE = 1;
    /** An uninstall is staged. */
    public static final int STAGED_OPERATION_UNINSTALL = 2;
    /** An install is staged. */
    public static final int STAGED_OPERATION_INSTALL = 3;

    @Retention(RetentionPolicy.SOURCE)
    @IntDef(prefix = { "DISTRO_STATUS_" }, value = {
            DISTRO_STATUS_UNKNOWN,
            DISTRO_STATUS_NONE,
            DISTRO_STATUS_INSTALLED
    })
    private @interface DistroStatus {}

    /** The current distro status could not be determined. */
    public static final int DISTRO_STATUS_UNKNOWN = 0;
    /** There is no active installed time zone distro. */
    public static final int DISTRO_STATUS_NONE = 1;
    /** The is an active, installed time zone distro. */
    public static final int DISTRO_STATUS_INSTALLED = 2;

    private static final byte BYTE_FALSE = 0;
    private static final byte BYTE_TRUE = 1;

    private final String mBaseRulesVersion;
    private final DistroFormatVersion mDistroFormatVersionSupported;
    private final boolean mOperationInProgress;
    @StagedOperationType private final int mStagedOperationType;
    @Nullable private final DistroRulesVersion mStagedDistroRulesVersion;
    @DistroStatus private final int mDistroStatus;
    @Nullable private final DistroRulesVersion mInstalledDistroRulesVersion;

    public RulesState(String baseRulesVersion, DistroFormatVersion distroFormatVersionSupported,
            boolean operationInProgress,
            @StagedOperationType int stagedOperationType,
            @Nullable DistroRulesVersion stagedDistroRulesVersion,
            @DistroStatus int distroStatus,
            @Nullable DistroRulesVersion installedDistroRulesVersion) {
        this.mBaseRulesVersion = validateRulesVersion("baseRulesVersion", baseRulesVersion);
        this.mDistroFormatVersionSupported =
                validateNotNull("distroFormatVersionSupported", distroFormatVersionSupported);
        this.mOperationInProgress = operationInProgress;

        if (operationInProgress && stagedOperationType != STAGED_OPERATION_UNKNOWN) {
            throw new IllegalArgumentException(
                    "stagedOperationType != STAGED_OPERATION_UNKNOWN");
        }
        this.mStagedOperationType = validateStagedOperation(stagedOperationType);
        this.mStagedDistroRulesVersion = validateConditionalNull(
                mStagedOperationType == STAGED_OPERATION_INSTALL /* requireNotNull */,
                "stagedDistroRulesVersion", stagedDistroRulesVersion);

        this.mDistroStatus = validateDistroStatus(distroStatus);
        this.mInstalledDistroRulesVersion = validateConditionalNull(
                mDistroStatus == DISTRO_STATUS_INSTALLED/* requireNotNull */,
                "installedDistroRulesVersion", installedDistroRulesVersion);
    }

    public String getBaseRulesVersion() {
        return mBaseRulesVersion;
    }

    public boolean isOperationInProgress() {
        return mOperationInProgress;
    }

    public @StagedOperationType int getStagedOperationType() {
        return mStagedOperationType;
    }

    /**
     * Returns the staged rules version when {@link #getStagedOperationType()} is
     * {@link #STAGED_OPERATION_INSTALL}.
     */
    public @Nullable DistroRulesVersion getStagedDistroRulesVersion() {
        return mStagedDistroRulesVersion;
    }

    public @DistroStatus int getDistroStatus() {
        return mDistroStatus;
    }

    /**
     * Returns the installed rules version when {@link #getDistroStatus()} is
     * {@link #DISTRO_STATUS_INSTALLED}.
     */
    public @Nullable DistroRulesVersion getInstalledDistroRulesVersion() {
        return mInstalledDistroRulesVersion;
    }

    /**
     * Returns true if a distro in the specified format is supported on this device.
     */
    public boolean isDistroFormatVersionSupported(DistroFormatVersion distroFormatVersion) {
        return mDistroFormatVersionSupported.supports(distroFormatVersion);
    }

    /**
     * Returns true if the base data files contain IANA rules data that are newer than the
     * distro IANA rules version supplied, i.e. true when the version specified would be "worse"
     * than the one that is in the base data. Returns false if the base version is the
     * same or older, i.e. false when the version specified would be "better" than the one that is
     * in the base set.
     */
    public boolean isBaseVersionNewerThan(DistroRulesVersion distroRulesVersion) {
        return mBaseRulesVersion.compareTo(distroRulesVersion.getRulesVersion()) > 0;
    }

    public static final Parcelable.Creator<RulesState> CREATOR =
            new Parcelable.Creator<RulesState>() {
        public RulesState createFromParcel(Parcel in) {
            return RulesState.createFromParcel(in);
        }

        public RulesState[] newArray(int size) {
            return new RulesState[size];
        }
    };

    private static RulesState createFromParcel(Parcel in) {
        String baseRulesVersion = in.readString();
        DistroFormatVersion distroFormatVersionSupported = in.readParcelable(null);
        boolean operationInProgress = in.readByte() == BYTE_TRUE;
        int distroStagedState = in.readByte();
        DistroRulesVersion stagedDistroRulesVersion = in.readParcelable(null);
        int installedDistroStatus = in.readByte();
        DistroRulesVersion installedDistroRulesVersion = in.readParcelable(null);
        return new RulesState(baseRulesVersion, distroFormatVersionSupported, operationInProgress,
                distroStagedState, stagedDistroRulesVersion,
                installedDistroStatus, installedDistroRulesVersion);
    }

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

    @Override
    public void writeToParcel(Parcel out, int flags) {
        out.writeString(mBaseRulesVersion);
        out.writeParcelable(mDistroFormatVersionSupported, 0);
        out.writeByte(mOperationInProgress ? BYTE_TRUE : BYTE_FALSE);
        out.writeByte((byte) mStagedOperationType);
        out.writeParcelable(mStagedDistroRulesVersion, 0);
        out.writeByte((byte) mDistroStatus);
        out.writeParcelable(mInstalledDistroRulesVersion, 0);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }

        RulesState that = (RulesState) o;

        if (mOperationInProgress != that.mOperationInProgress) {
            return false;
        }
        if (mStagedOperationType != that.mStagedOperationType) {
            return false;
        }
        if (mDistroStatus != that.mDistroStatus) {
            return false;
        }
        if (!mBaseRulesVersion.equals(that.mBaseRulesVersion)) {
            return false;
        }
        if (!mDistroFormatVersionSupported.equals(that.mDistroFormatVersionSupported)) {
            return false;
        }
        if (mStagedDistroRulesVersion != null ? !mStagedDistroRulesVersion
                .equals(that.mStagedDistroRulesVersion) : that.mStagedDistroRulesVersion != null) {
            return false;
        }
        return mInstalledDistroRulesVersion != null ? mInstalledDistroRulesVersion
                .equals(that.mInstalledDistroRulesVersion)
                : that.mInstalledDistroRulesVersion == null;
    }

    @Override
    public int hashCode() {
        int result = mBaseRulesVersion.hashCode();
        result = 31 * result + mDistroFormatVersionSupported.hashCode();
        result = 31 * result + (mOperationInProgress ? 1 : 0);
        result = 31 * result + mStagedOperationType;
        result = 31 * result + (mStagedDistroRulesVersion != null ? mStagedDistroRulesVersion
                .hashCode()
                : 0);
        result = 31 * result + mDistroStatus;
        result = 31 * result + (mInstalledDistroRulesVersion != null ? mInstalledDistroRulesVersion
                .hashCode() : 0);
        return result;
    }

    @Override
    public String toString() {
        return "RulesState{"
                + "mBaseRulesVersion='" + mBaseRulesVersion + '\''
                + ", mDistroFormatVersionSupported=" + mDistroFormatVersionSupported
                + ", mOperationInProgress=" + mOperationInProgress
                + ", mStagedOperationType=" + mStagedOperationType
                + ", mStagedDistroRulesVersion=" + mStagedDistroRulesVersion
                + ", mDistroStatus=" + mDistroStatus
                + ", mInstalledDistroRulesVersion=" + mInstalledDistroRulesVersion
                + '}';
    }

    private static int validateStagedOperation(int stagedOperationType) {
        if (stagedOperationType < STAGED_OPERATION_UNKNOWN
                || stagedOperationType > STAGED_OPERATION_INSTALL) {
            throw new IllegalArgumentException("Unknown operation type=" + stagedOperationType);
        }
        return stagedOperationType;
    }

    private static int validateDistroStatus(int distroStatus) {
        if (distroStatus < DISTRO_STATUS_UNKNOWN || distroStatus > DISTRO_STATUS_INSTALLED) {
            throw new IllegalArgumentException("Unknown distro status=" + distroStatus);
        }
        return distroStatus;
    }
}
