/*
 * 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.telecom;

import android.annotation.FloatRange;
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;

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

/**
 * Represents attributes of video calls.
 */
public class VideoProfile implements Parcelable {

    /** @hide */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({QUALITY_UNKNOWN, QUALITY_HIGH, QUALITY_MEDIUM, QUALITY_LOW, QUALITY_DEFAULT})
    public @interface VideoQuality {}

    /**
     * "Unknown" video quality.
     * @hide
     */
    public static final int QUALITY_UNKNOWN = 0;
    /**
     * "High" video quality.
     */
    public static final int QUALITY_HIGH = 1;

    /**
     * "Medium" video quality.
     */
    public static final int QUALITY_MEDIUM = 2;

    /**
     * "Low" video quality.
     */
    public static final int QUALITY_LOW = 3;

    /**
     * Use default video quality.
     */
    public static final int QUALITY_DEFAULT = 4;

    /** @hide */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(
            flag = true,
            prefix = { "STATE_" },
            value = {STATE_AUDIO_ONLY, STATE_TX_ENABLED, STATE_RX_ENABLED, STATE_BIDIRECTIONAL,
                    STATE_PAUSED})
    public @interface VideoState {}

    /**
     * Used when answering or dialing a call to indicate that the call does not have a video
     * component.
     * <p>
     * Should <b>not</b> be used in comparison checks to determine if a video state represents an
     * audio-only call.
     * <p>
     * The following, for example, is not the correct way to check if a call is audio-only:
     * <pre>
     * {@code
     * // This is the incorrect way to check for an audio-only call.
     * if (videoState == VideoProfile.STATE_AUDIO_ONLY) {
     *      // Handle audio-only call.
     * }
     * }
     * </pre>
     * <p>
     * Instead, use the {@link VideoProfile#isAudioOnly(int)} helper function to check if a
     * video state represents an audio-only call:
     * <pre>
     * {@code
     * // This is the correct way to check for an audio-only call.
     * if (VideoProfile.isAudioOnly(videoState)) {
     *      // Handle audio-only call.
     * }
     * }
     * </pre>
     */
    public static final int STATE_AUDIO_ONLY = 0x0;

    /**
     * Video transmission is enabled.
     */
    public static final int STATE_TX_ENABLED = 0x1;

    /**
     * Video reception is enabled.
     */
    public static final int STATE_RX_ENABLED = 0x2;

    /**
     * Video signal is bi-directional.
     */
    public static final int STATE_BIDIRECTIONAL = STATE_TX_ENABLED | STATE_RX_ENABLED;

    /**
     * Video is paused.
     */
    public static final int STATE_PAUSED = 0x4;

    private final int mVideoState;

    private final int mQuality;

    /**
     * Creates an instance of the VideoProfile
     *
     * @param videoState The video state.
     */
    public VideoProfile(@VideoState int videoState) {
        this(videoState, QUALITY_DEFAULT);
    }

    /**
     * Creates an instance of the VideoProfile
     *
     * @param videoState The video state.
     * @param quality The video quality.
     */
    public VideoProfile(@VideoState int videoState, @VideoQuality int quality) {
        mVideoState = videoState;
        mQuality = quality;
    }

    /**
     * The video state of the call.
     * Valid values: {@link VideoProfile#STATE_AUDIO_ONLY},
     * {@link VideoProfile#STATE_BIDIRECTIONAL},
     * {@link VideoProfile#STATE_TX_ENABLED},
     * {@link VideoProfile#STATE_RX_ENABLED},
     * {@link VideoProfile#STATE_PAUSED}.
     */
    @VideoState
    public int getVideoState() {
        return mVideoState;
    }

    /**
     * The desired video quality for the call.
     * Valid values: {@link VideoProfile#QUALITY_HIGH}, {@link VideoProfile#QUALITY_MEDIUM},
     * {@link VideoProfile#QUALITY_LOW}, {@link VideoProfile#QUALITY_DEFAULT}.
     */
    @VideoQuality
    public int getQuality() {
        return mQuality;
    }

    /**
     * Responsible for creating VideoProfile objects from deserialized Parcels.
     **/
    public static final @android.annotation.NonNull Parcelable.Creator<VideoProfile> CREATOR =
            new Parcelable.Creator<VideoProfile> () {
                /**
                 * Creates a MediaProfile instances from a parcel.
                 *
                 * @param source The parcel.
                 * @return The MediaProfile.
                 */
                @Override
                public VideoProfile createFromParcel(Parcel source) {
                    int state = source.readInt();
                    int quality = source.readInt();

                    ClassLoader classLoader = VideoProfile.class.getClassLoader();
                    return new VideoProfile(state, quality);
                }

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

    /**
     * Describe the kinds of special objects contained in this Parcelable's
     * marshalled representation.
     *
     * @return a bitmask indicating the set of special object types marshalled
     * by the Parcelable.
     */
    @Override
    public int describeContents() {
        return 0;
    }

    /**
     * Flatten this object in to a Parcel.
     *
     * @param dest  The Parcel in which the object should be written.
     * @param flags Additional flags about how the object should be written.
     *              May be 0 or {@link #PARCELABLE_WRITE_RETURN_VALUE}.
     */
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(mVideoState);
        dest.writeInt(mQuality);
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("[VideoProfile videoState = ");
        sb.append(videoStateToString(mVideoState));
        sb.append(" videoQuality = ");
        sb.append(mQuality);
        sb.append("]");
        return sb.toString();
    }

    /**
     * Generates a string representation of a video state.
     *
     * @param videoState The video state.
     * @return String representation of the video state.
     */
    public static String videoStateToString(@VideoState int videoState) {
        StringBuilder sb = new StringBuilder();
        sb.append("Audio");

        if (videoState == STATE_AUDIO_ONLY) {
            sb.append(" Only");
        } else {
            if (isTransmissionEnabled(videoState)) {
                sb.append(" Tx");
            }

            if (isReceptionEnabled(videoState)) {
                sb.append(" Rx");
            }

            if (isPaused(videoState)) {
                sb.append(" Pause");
            }
        }

        return sb.toString();
    }

    /**
     * Indicates whether the video state is audio only.
     * <p>
     * Note: Considers only whether either both the {@link #STATE_RX_ENABLED} or
     * {@link #STATE_TX_ENABLED} bits are off, but not {@link #STATE_PAUSED}.
     *
     * @param videoState The video state.
     * @return {@code True} if the video state is audio only, {@code false} otherwise.
     */
    public static boolean isAudioOnly(@VideoState int videoState) {
        return !hasState(videoState, VideoProfile.STATE_TX_ENABLED)
                && !hasState(videoState, VideoProfile.STATE_RX_ENABLED);
    }

    /**
     * Indicates whether video transmission or reception is enabled for a video state.
     *
     * @param videoState The video state.
     * @return {@code True} if video transmission or reception is enabled, {@code false} otherwise.
     */
    public static boolean isVideo(@VideoState int videoState) {
        return hasState(videoState, VideoProfile.STATE_TX_ENABLED)
                || hasState(videoState, VideoProfile.STATE_RX_ENABLED)
                || hasState(videoState, VideoProfile.STATE_BIDIRECTIONAL);
    }

    /**
     * Indicates whether the video state has video transmission enabled.
     *
     * @param videoState The video state.
     * @return {@code True} if video transmission is enabled, {@code false} otherwise.
     */
    public static boolean isTransmissionEnabled(@VideoState int videoState) {
        return hasState(videoState, VideoProfile.STATE_TX_ENABLED);
    }

    /**
     * Indicates whether the video state has video reception enabled.
     *
     * @param videoState The video state.
     * @return {@code True} if video reception is enabled, {@code false} otherwise.
     */
    public static boolean isReceptionEnabled(@VideoState int videoState) {
        return hasState(videoState, VideoProfile.STATE_RX_ENABLED);
    }

    /**
     * Indicates whether the video state is bi-directional.
     *
     * @param videoState The video state.
     * @return {@code True} if the video is bi-directional, {@code false} otherwise.
     */
    public static boolean isBidirectional(@VideoState int videoState) {
        return hasState(videoState, VideoProfile.STATE_BIDIRECTIONAL);
    }

    /**
     * Indicates whether the video state is paused.
     *
     * @param videoState The video state.
     * @return {@code True} if the video is paused, {@code false} otherwise.
     */
    public static boolean isPaused(@VideoState int videoState) {
        return hasState(videoState, VideoProfile.STATE_PAUSED);
    }

    /**
     * Indicates if a specified state is set in a videoState bit-mask.
     *
     * @param videoState The video state bit-mask.
     * @param state The state to check.
     * @return {@code True} if the state is set.
     */
    private static boolean hasState(@VideoState int videoState, @VideoState int state) {
        return (videoState & state) == state;
    }

    /**
     * Represents the camera capabilities important to a Video Telephony provider.
     */
    public static final class CameraCapabilities implements Parcelable {

        /**
         * The width of the camera video in pixels.
         */
        private final int mWidth;

        /**
         * The height of the camera video in pixels.
         */
        private final int mHeight;

        /**
         * Whether the camera supports zoom.
         */
        private final boolean mZoomSupported;

        /**
         * The maximum zoom supported by the camera.
         */
        private final float mMaxZoom;

        /**
         * Create a call camera capabilities instance.
         *
         * @param width The width of the camera video (in pixels).
         * @param height The height of the camera video (in pixels).
         */
        public CameraCapabilities(@IntRange(from = 0) int width, @IntRange(from = 0) int height) {
            this(width, height, false, 1.0f);
        }

        /**
         * Create a call camera capabilities instance that optionally supports zoom.
         *
         * @param width The width of the camera video (in pixels).
         * @param height The height of the camera video (in pixels).
         * @param zoomSupported True when camera supports zoom.
         * @param maxZoom Maximum zoom supported by camera.
         */
        public CameraCapabilities(@IntRange(from = 0) int width,  @IntRange(from = 0) int height,
                                   boolean zoomSupported,  @FloatRange(from = 1.0f) float maxZoom) {
            mWidth = width;
            mHeight = height;
            mZoomSupported = zoomSupported;
            mMaxZoom = maxZoom;
        }

        /**
         * Responsible for creating CallCameraCapabilities objects from deserialized Parcels.
         **/
        public static final @android.annotation.NonNull Parcelable.Creator<CameraCapabilities> CREATOR =
                new Parcelable.Creator<CameraCapabilities> () {
                    /**
                     * Creates a CallCameraCapabilities instances from a parcel.
                     *
                     * @param source The parcel.
                     * @return The CallCameraCapabilities.
                     */
                    @Override
                    public CameraCapabilities createFromParcel(Parcel source) {
                        int width = source.readInt();
                        int height = source.readInt();
                        boolean supportsZoom = source.readByte() != 0;
                        float maxZoom = source.readFloat();

                        return new CameraCapabilities(width, height, supportsZoom, maxZoom);
                    }

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

        /**
         * Describe the kinds of special objects contained in this Parcelable's
         * marshalled representation.
         *
         * @return a bitmask indicating the set of special object types marshalled
         * by the Parcelable.
         */
        @Override
        public int describeContents() {
            return 0;
        }

        /**
         * Flatten this object in to a Parcel.
         *
         * @param dest  The Parcel in which the object should be written.
         * @param flags Additional flags about how the object should be written.
         *              May be 0 or {@link #PARCELABLE_WRITE_RETURN_VALUE}.
         */
        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeInt(getWidth());
            dest.writeInt(getHeight());
            dest.writeByte((byte) (isZoomSupported() ? 1 : 0));
            dest.writeFloat(getMaxZoom());
        }

        /**
         * The width of the camera video in pixels.
         */
        public int getWidth() {
            return mWidth;
        }

        /**
         * The height of the camera video in pixels.
         */
        public int getHeight() {
            return mHeight;
        }

        /**
         * Returns {@code true} is zoom is supported, {@code false} otherwise.
         */
        public boolean isZoomSupported() {
            return mZoomSupported;
        }

        /**
         * Returns the maximum zoom supported by the camera.
         */
        public float getMaxZoom() {
            return mMaxZoom;
        }
    }

}
