/*
 * Copyright (C) 2022 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.media;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.content.Context;
import android.media.audiopolicy.AudioVolumeGroup;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;

import java.util.Objects;

/**
 * @hide
 * A class to represent volume information.
 * Can be used to represent volume associated with a stream type or {@link AudioVolumeGroup}.
 * Volume index is optional when used to represent a category of volume.
 * Volume ranges are supported too, making the representation of volume changes agnostic regarding
 * the range of values that are supported (e.g. can be used to map BT A2DP absolute volume range to
 * internal range).
 */
@SystemApi
public final class VolumeInfo implements Parcelable {
    private static final String TAG = "VolumeInfo";

    private final boolean mUsesStreamType; // false implies AudioVolumeGroup is used
    private final boolean mHasMuteCommand;
    private final boolean mIsMuted;
    private final int mVolIndex;
    private final int mMinVolIndex;
    private final int mMaxVolIndex;
    private final @Nullable AudioVolumeGroup mVolGroup;
    private final @AudioManager.PublicStreamTypes int mStreamType;

    private static IAudioService sService;
    private static VolumeInfo sDefaultVolumeInfo;

    private VolumeInfo(boolean usesStreamType, boolean hasMuteCommand, boolean isMuted,
            int volIndex, int minVolIndex, int maxVolIndex,
            AudioVolumeGroup volGroup, int streamType) {
        mUsesStreamType = usesStreamType;
        mHasMuteCommand = hasMuteCommand;
        mIsMuted = isMuted;
        mVolIndex = volIndex;
        mMinVolIndex = minVolIndex;
        mMaxVolIndex = maxVolIndex;
        mVolGroup = volGroup;
        mStreamType = streamType;
    }

    /**
     * Indicates whether this instance has a stream type associated to it.
     * Note this method returning true implies {@link #hasVolumeGroup()} returns false.
     * (e.g. {@link AudioManager#STREAM_MUSIC}).
     * @return true if it has stream type information
     */
    public boolean hasStreamType() {
        return mUsesStreamType;
    }

    /**
     * Returns the associated stream type, or will throw if {@link #hasStreamType()} returned false.
     * @return a stream type value, see AudioManager.STREAM_*
     * @throws IllegalStateException when called on a VolumeInfo not configured for
     *      stream types.
     */
    public @AudioManager.PublicStreamTypes int getStreamType() {
        if (!mUsesStreamType) {
            throw new IllegalStateException("VolumeInfo doesn't use stream types");
        }
        return mStreamType;
    }

    /**
     * Indicates whether this instance has a {@link AudioVolumeGroup} associated to it.
     * Note this method returning true implies {@link #hasStreamType()} returns false.
     * @return true if it has volume group information
     */
    public boolean hasVolumeGroup() {
        return !mUsesStreamType;
    }

    /**
     * Returns the associated volume group, or will throw if {@link #hasVolumeGroup()} returned
     * false.
     * @return the volume group corresponding to this VolumeInfo
     * @throws IllegalStateException when called on a VolumeInfo not configured for
     * volume groups.
     */
    public @NonNull AudioVolumeGroup getVolumeGroup() {
        if (mUsesStreamType) {
            throw new IllegalStateException("VolumeInfo doesn't use AudioVolumeGroup");
        }
        return mVolGroup;
    }

    /**
     * Return whether this instance is conveying a mute state
     * @return true if the muted state was explicitly set for this instance
     */
    public boolean hasMuteCommand() {
        return mHasMuteCommand;
    }

    /**
     * Returns whether this instance is conveying a mute state that was explicitly set
     * by {@link Builder#setMuted(boolean)}, false otherwise
     * @return true if the volume state is muted
     */
    public boolean isMuted() {
        return mIsMuted;
    }

    /**
     * A value used to express no volume index has been set.
     */
    public static final int INDEX_NOT_SET = -100;

    /**
     * Returns the volume index.
     * @return a volume index, or {@link #INDEX_NOT_SET} if no index was set, in which case this
     *      instance is used to express a volume representation type (stream vs group) and
     *      optionally its volume range
     */
    public int getVolumeIndex() {
        return mVolIndex;
    }

    /**
     * Returns the minimum volume index.
     * @return the minimum volume index, or {@link #INDEX_NOT_SET} if no minimum index was set.
     */
    public int getMinVolumeIndex() {
        return mMinVolIndex;
    }

    /**
     * Returns the maximum volume index.
     * @return the maximum volume index, or {@link #INDEX_NOT_SET} if no maximum index was
     *      set.
     */
    public int getMaxVolumeIndex() {
        return mMaxVolIndex;
    }

    /**
     * Returns the default info for the platform, typically initialized
     * to STREAM_MUSIC with min/max initialized to the associated range
     * @return the default VolumeInfo for the device
     */
    public static @NonNull VolumeInfo getDefaultVolumeInfo() {
        if (sService == null) {
            IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
            sService = IAudioService.Stub.asInterface(b);
        }
        if (sDefaultVolumeInfo == null) {
            try {
                sDefaultVolumeInfo = sService.getDefaultVolumeInfo();
            } catch (RemoteException e) {
                Log.e(TAG, "Error calling getDefaultVolumeInfo", e);
                // return a valid value, but don't cache it
                return new VolumeInfo.Builder(AudioManager.STREAM_MUSIC).build();
            }
        }
        return sDefaultVolumeInfo;
    }

    /**
     * The builder class for creating and initializing, or copying and modifying VolumeInfo
     * instances
     */
    public static final class Builder {
        private boolean mUsesStreamType = true; // false implies AudioVolumeGroup is used
        private @AudioManager.PublicStreamTypes int mStreamType = AudioManager.STREAM_MUSIC;
        private boolean mHasMuteCommand = false;
        private boolean mIsMuted = false;
        private int mVolIndex = INDEX_NOT_SET;
        private int mMinVolIndex = INDEX_NOT_SET;
        private int mMaxVolIndex = INDEX_NOT_SET;
        private @Nullable AudioVolumeGroup mVolGroup;

        /**
         * Builder constructor for stream type-based VolumeInfo
         */
        public Builder(@AudioManager.PublicStreamTypes int streamType) {
            if (!AudioManager.isPublicStreamType(streamType)) {
                throw new IllegalArgumentException("Not a valid public stream type " + streamType);
            }
            mUsesStreamType = true;
            mStreamType = streamType;
        }

        /**
         * Builder constructor for volume group-based VolumeInfo
         */
        public Builder(@NonNull AudioVolumeGroup volGroup) {
            Objects.requireNonNull(volGroup);
            mUsesStreamType = false;
            mStreamType = -Integer.MIN_VALUE;
            mVolGroup = volGroup;
        }

        /**
         * Builder constructor to copy a given VolumeInfo.
         * Note you can't change the stream type or volume group later.
         */
        public Builder(@NonNull VolumeInfo info) {
            Objects.requireNonNull(info);
            mUsesStreamType = info.mUsesStreamType;
            mStreamType = info.mStreamType;
            mHasMuteCommand = info.mHasMuteCommand;
            mIsMuted = info.mIsMuted;
            mVolIndex = info.mVolIndex;
            mMinVolIndex = info.mMinVolIndex;
            mMaxVolIndex = info.mMaxVolIndex;
            mVolGroup = info.mVolGroup;
        }

        /**
         * Sets whether the volume is in a muted state
         * @param isMuted
         * @return the same builder instance
         */
        public @NonNull Builder setMuted(boolean isMuted) {
            mHasMuteCommand = true;
            mIsMuted = isMuted;
            return this;
        }

        /**
         * Sets the volume index
         * @param volIndex a 0 or greater value, or {@link #INDEX_NOT_SET} if unknown
         * @return the same builder instance
         */
        public @NonNull Builder setVolumeIndex(int volIndex) {
            if (volIndex != INDEX_NOT_SET && volIndex < 0) {
                throw new IllegalArgumentException("Volume index cannot be negative");
            }
            mVolIndex = volIndex;
            return this;
        }

        /**
         * Sets the minimum volume index
         * @param minIndex a 0 or greater value, or {@link #INDEX_NOT_SET} if unknown
         * @return the same builder instance
         */
        public @NonNull Builder setMinVolumeIndex(int minIndex) {
            if (minIndex != INDEX_NOT_SET && minIndex < 0) {
                throw new IllegalArgumentException("Min volume index cannot be negative");
            }
            mMinVolIndex = minIndex;
            return this;
        }

        /**
         * Sets the maximum volume index
         * @param maxIndex a 0 or greater value, or {@link #INDEX_NOT_SET} if unknown
         * @return the same builder instance
         */
        public @NonNull Builder setMaxVolumeIndex(int maxIndex) {
            if (maxIndex != INDEX_NOT_SET && maxIndex < 0) {
                throw new IllegalArgumentException("Max volume index cannot be negative");
            }
            mMaxVolIndex = maxIndex;
            return this;
        }

        /**
         * Builds the VolumeInfo with the data given to the builder
         * @return the new VolumeInfo instance
         */
        public @NonNull VolumeInfo build() {
            if (mVolIndex != INDEX_NOT_SET) {
                if (mMinVolIndex != INDEX_NOT_SET && mVolIndex < mMinVolIndex) {
                    throw new IllegalArgumentException("Volume index:" + mVolIndex
                            + " lower than min index:" + mMinVolIndex);
                }
                if (mMaxVolIndex != INDEX_NOT_SET && mVolIndex > mMaxVolIndex) {
                    throw new IllegalArgumentException("Volume index:" + mVolIndex
                            + " greater than max index:" + mMaxVolIndex);
                }
            }
            if (mMinVolIndex != INDEX_NOT_SET && mMaxVolIndex != INDEX_NOT_SET
                    && mMinVolIndex > mMaxVolIndex) {
                throw new IllegalArgumentException("Min volume index:" + mMinVolIndex
                        + " greater than max index:" + mMaxVolIndex);
            }
            return new VolumeInfo(mUsesStreamType, mHasMuteCommand, mIsMuted,
                    mVolIndex, mMinVolIndex, mMaxVolIndex,
                    mVolGroup, mStreamType);
        }
    }

    //-----------------------------------------------
    // Parcelable
    @Override
    public int hashCode() {
        return Objects.hash(mUsesStreamType, mHasMuteCommand, mStreamType, mIsMuted,
                mVolIndex, mMinVolIndex, mMaxVolIndex, mVolGroup);
    }

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

        VolumeInfo that = (VolumeInfo) o;
        return ((mUsesStreamType == that.mUsesStreamType)
                && (mStreamType == that.mStreamType)
                && (mHasMuteCommand == that.mHasMuteCommand)
                && (mIsMuted == that.mIsMuted)
                && (mVolIndex == that.mVolIndex)
                && (mMinVolIndex == that.mMinVolIndex)
                && (mMaxVolIndex == that.mMaxVolIndex)
                && Objects.equals(mVolGroup, that.mVolGroup));
    }

    @Override
    public String toString() {
        return new String("VolumeInfo:"
                + (mUsesStreamType ? (" streamType:" + mStreamType)
                    : (" volGroup:" + mVolGroup))
                + (mHasMuteCommand ? (" muted:" + mIsMuted) : ("[no mute cmd]"))
                + ((mVolIndex != INDEX_NOT_SET) ? (" volIndex:" + mVolIndex) : "")
                + ((mMinVolIndex != INDEX_NOT_SET) ? (" min:" + mMinVolIndex) : "")
                + ((mMaxVolIndex != INDEX_NOT_SET) ? (" max:" + mMaxVolIndex) : ""));
    }

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

    @Override
    public void writeToParcel(@NonNull Parcel dest, int flags) {
        dest.writeBoolean(mUsesStreamType);
        dest.writeInt(mStreamType);
        dest.writeBoolean(mHasMuteCommand);
        dest.writeBoolean(mIsMuted);
        dest.writeInt(mVolIndex);
        dest.writeInt(mMinVolIndex);
        dest.writeInt(mMaxVolIndex);
        if (!mUsesStreamType) {
            mVolGroup.writeToParcel(dest, 0 /*ignored*/);
        }
    }

    private VolumeInfo(@NonNull Parcel in) {
        mUsesStreamType = in.readBoolean();
        mStreamType = in.readInt();
        mHasMuteCommand = in.readBoolean();
        mIsMuted = in.readBoolean();
        mVolIndex = in.readInt();
        mMinVolIndex = in.readInt();
        mMaxVolIndex = in.readInt();
        if (!mUsesStreamType) {
            mVolGroup = AudioVolumeGroup.CREATOR.createFromParcel(in);
        } else {
            mVolGroup = null;
        }
    }

    public static final @NonNull Parcelable.Creator<VolumeInfo> CREATOR =
            new Parcelable.Creator<VolumeInfo>() {
                /**
                 * Rebuilds a VolumeInfo previously stored with writeToParcel().
                 * @param p Parcel object to read the VolumeInfo from
                 * @return a new VolumeInfo created from the data in the parcel
                 */
                public VolumeInfo createFromParcel(Parcel p) {
                    return new VolumeInfo(p);
                }

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