/*
 * Copyright (C) 2016 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.net.wifi.aware;

import android.os.Parcel;
import android.os.Parcelable;

import java.util.Arrays;

/**
 * Defines a request object to configure a Wi-Fi Aware network. Built using
 * {@link ConfigRequest.Builder}. Configuration is requested using
 * {@link WifiAwareManager#attach(AttachCallback, android.os.Handler)}.
 * Note that the actual achieved configuration may be different from the
 * requested configuration - since different applications may request different
 * configurations.
 *
 * @hide
 */
public final class ConfigRequest implements Parcelable {
    /**
     * Lower range of possible cluster ID.
     */
    public static final int CLUSTER_ID_MIN = 0;

    /**
     * Upper range of possible cluster ID.
     */
    public static final int CLUSTER_ID_MAX = 0xFFFF;

    /**
     * Indices for configuration variables which are specified per band.
     */
    public static final int NAN_BAND_24GHZ = 0;
    public static final int NAN_BAND_5GHZ = 1;

    /**
     * Magic values for Discovery Window (DW) interval configuration
     */
    public static final int DW_INTERVAL_NOT_INIT = -1;
    public static final int DW_DISABLE = 0; // only valid for 5GHz

    /**
     * Indicates whether 5G band support is requested.
     */
    public final boolean mSupport5gBand;

    /**
     * Specifies the desired master preference.
     */
    public final int mMasterPreference;

    /**
     * Specifies the desired lower range of the cluster ID. Must be lower then
     * {@link ConfigRequest#mClusterHigh}.
     */
    public final int mClusterLow;

    /**
     * Specifies the desired higher range of the cluster ID. Must be higher then
     * {@link ConfigRequest#mClusterLow}.
     */
    public final int mClusterHigh;

    /**
     * Specifies the discovery window interval for the device on NAN_BAND_*.
     */
    public final int mDiscoveryWindowInterval[];

    private ConfigRequest(boolean support5gBand, int masterPreference, int clusterLow,
            int clusterHigh, int discoveryWindowInterval[]) {
        mSupport5gBand = support5gBand;
        mMasterPreference = masterPreference;
        mClusterLow = clusterLow;
        mClusterHigh = clusterHigh;
        mDiscoveryWindowInterval = discoveryWindowInterval;
    }

    @Override
    public String toString() {
        return "ConfigRequest [mSupport5gBand=" + mSupport5gBand + ", mMasterPreference="
                + mMasterPreference + ", mClusterLow=" + mClusterLow + ", mClusterHigh="
                + mClusterHigh + ", mDiscoveryWindowInterval="
                + Arrays.toString(mDiscoveryWindowInterval) + "]";
    }

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(mSupport5gBand ? 1 : 0);
        dest.writeInt(mMasterPreference);
        dest.writeInt(mClusterLow);
        dest.writeInt(mClusterHigh);
        dest.writeIntArray(mDiscoveryWindowInterval);
    }

    public static final @android.annotation.NonNull Creator<ConfigRequest> CREATOR = new Creator<ConfigRequest>() {
        @Override
        public ConfigRequest[] newArray(int size) {
            return new ConfigRequest[size];
        }

        @Override
        public ConfigRequest createFromParcel(Parcel in) {
            boolean support5gBand = in.readInt() != 0;
            int masterPreference = in.readInt();
            int clusterLow = in.readInt();
            int clusterHigh = in.readInt();
            int discoveryWindowInterval[] = in.createIntArray();

            return new ConfigRequest(support5gBand, masterPreference, clusterLow, clusterHigh,
                    discoveryWindowInterval);
        }
    };

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }

        if (!(o instanceof ConfigRequest)) {
            return false;
        }

        ConfigRequest lhs = (ConfigRequest) o;

        return mSupport5gBand == lhs.mSupport5gBand && mMasterPreference == lhs.mMasterPreference
                && mClusterLow == lhs.mClusterLow && mClusterHigh == lhs.mClusterHigh
                && Arrays.equals(mDiscoveryWindowInterval, lhs.mDiscoveryWindowInterval);
    }

    @Override
    public int hashCode() {
        int result = 17;

        result = 31 * result + (mSupport5gBand ? 1 : 0);
        result = 31 * result + mMasterPreference;
        result = 31 * result + mClusterLow;
        result = 31 * result + mClusterHigh;
        result = 31 * result + Arrays.hashCode(mDiscoveryWindowInterval);

        return result;
    }

    /**
     * Verifies that the contents of the ConfigRequest are valid. Otherwise
     * throws an IllegalArgumentException.
     */
    public void validate() throws IllegalArgumentException {
        if (mMasterPreference < 0) {
            throw new IllegalArgumentException(
                    "Master Preference specification must be non-negative");
        }
        if (mMasterPreference == 1 || mMasterPreference == 255 || mMasterPreference > 255) {
            throw new IllegalArgumentException("Master Preference specification must not "
                    + "exceed 255 or use 1 or 255 (reserved values)");
        }
        if (mClusterLow < CLUSTER_ID_MIN) {
            throw new IllegalArgumentException("Cluster specification must be non-negative");
        }
        if (mClusterLow > CLUSTER_ID_MAX) {
            throw new IllegalArgumentException("Cluster specification must not exceed 0xFFFF");
        }
        if (mClusterHigh < CLUSTER_ID_MIN) {
            throw new IllegalArgumentException("Cluster specification must be non-negative");
        }
        if (mClusterHigh > CLUSTER_ID_MAX) {
            throw new IllegalArgumentException("Cluster specification must not exceed 0xFFFF");
        }
        if (mClusterLow > mClusterHigh) {
            throw new IllegalArgumentException(
                    "Invalid argument combination - must have Cluster Low <= Cluster High");
        }
        if (mDiscoveryWindowInterval.length != 2) {
            throw new IllegalArgumentException(
                    "Invalid discovery window interval: must have 2 elements (2.4 & 5");
        }
        if (mDiscoveryWindowInterval[NAN_BAND_24GHZ] != DW_INTERVAL_NOT_INIT &&
                (mDiscoveryWindowInterval[NAN_BAND_24GHZ] < 1 // valid for 2.4GHz: [1-5]
                || mDiscoveryWindowInterval[NAN_BAND_24GHZ] > 5)) {
            throw new IllegalArgumentException(
                    "Invalid discovery window interval for 2.4GHz: valid is UNSET or [1,5]");
        }
        if (mDiscoveryWindowInterval[NAN_BAND_5GHZ] != DW_INTERVAL_NOT_INIT &&
                (mDiscoveryWindowInterval[NAN_BAND_5GHZ] < 0 // valid for 5GHz: [0-5]
                || mDiscoveryWindowInterval[NAN_BAND_5GHZ] > 5)) {
            throw new IllegalArgumentException(
                "Invalid discovery window interval for 5GHz: valid is UNSET or [0,5]");
        }

    }

    /**
     * Builder used to build {@link ConfigRequest} objects.
     */
    public static final class Builder {
        private boolean mSupport5gBand = true;
        private int mMasterPreference = 0;
        private int mClusterLow = CLUSTER_ID_MIN;
        private int mClusterHigh = CLUSTER_ID_MAX;
        private int mDiscoveryWindowInterval[] = {DW_INTERVAL_NOT_INIT, DW_INTERVAL_NOT_INIT};

        /**
         * Specify whether 5G band support is required in this request. Disabled by default.
         *
         * @param support5gBand Support for 5G band is required.
         *
         * @return The builder to facilitate chaining
         *         {@code builder.setXXX(..).setXXX(..)}.
         */
        public Builder setSupport5gBand(boolean support5gBand) {
            mSupport5gBand = support5gBand;
            return this;
        }

        /**
         * Specify the Master Preference requested. The permitted range is 0 (the default) to
         * 255 with 1 and 255 excluded (reserved).
         *
         * @param masterPreference The requested master preference
         *
         * @return The builder to facilitate chaining
         *         {@code builder.setXXX(..).setXXX(..)}.
         */
        public Builder setMasterPreference(int masterPreference) {
            if (masterPreference < 0) {
                throw new IllegalArgumentException(
                        "Master Preference specification must be non-negative");
            }
            if (masterPreference == 1 || masterPreference == 255 || masterPreference > 255) {
                throw new IllegalArgumentException("Master Preference specification must not "
                        + "exceed 255 or use 1 or 255 (reserved values)");
            }

            mMasterPreference = masterPreference;
            return this;
        }

        /**
         * The Cluster ID is generated randomly for new Aware networks. Specify
         * the lower range of the cluster ID. The upper range is specified using
         * the {@link ConfigRequest.Builder#setClusterHigh(int)}. The permitted
         * range is 0 (the default) to the value specified by
         * {@link ConfigRequest.Builder#setClusterHigh(int)}. Equality of Low and High is
         * permitted which restricts the Cluster ID to the specified value.
         *
         * @param clusterLow The lower range of the generated cluster ID.
         *
         * @return The builder to facilitate chaining
         *         {@code builder.setClusterLow(..).setClusterHigh(..)}.
         */
        public Builder setClusterLow(int clusterLow) {
            if (clusterLow < CLUSTER_ID_MIN) {
                throw new IllegalArgumentException("Cluster specification must be non-negative");
            }
            if (clusterLow > CLUSTER_ID_MAX) {
                throw new IllegalArgumentException("Cluster specification must not exceed 0xFFFF");
            }

            mClusterLow = clusterLow;
            return this;
        }

        /**
         * The Cluster ID is generated randomly for new Aware networks. Specify
         * the lower upper of the cluster ID. The lower range is specified using
         * the {@link ConfigRequest.Builder#setClusterLow(int)}. The permitted
         * range is the value specified by
         * {@link ConfigRequest.Builder#setClusterLow(int)} to 0xFFFF (the default). Equality of
         * Low and High is permitted which restricts the Cluster ID to the specified value.
         *
         * @param clusterHigh The upper range of the generated cluster ID.
         *
         * @return The builder to facilitate chaining
         *         {@code builder.setClusterLow(..).setClusterHigh(..)}.
         */
        public Builder setClusterHigh(int clusterHigh) {
            if (clusterHigh < CLUSTER_ID_MIN) {
                throw new IllegalArgumentException("Cluster specification must be non-negative");
            }
            if (clusterHigh > CLUSTER_ID_MAX) {
                throw new IllegalArgumentException("Cluster specification must not exceed 0xFFFF");
            }

            mClusterHigh = clusterHigh;
            return this;
        }

        /**
         * The discovery window interval specifies the discovery windows in which the device will be
         * awake. The configuration enables trading off latency vs. power (higher interval means
         * higher discovery latency but lower power).
         *
         * @param band Either {@link #NAN_BAND_24GHZ} or {@link #NAN_BAND_5GHZ}.
         * @param interval A value of 1, 2, 3, 4, or 5 indicating an interval of 2^(interval-1). For
         *                 the 5GHz band a value of 0 indicates that the device will not be awake
         *                 for any discovery windows.
         *
         * @return The builder itself to facilitate chaining operations
         *         {@code builder.setDiscoveryWindowInterval(...).setMasterPreference(...)}.
         */
        public Builder setDiscoveryWindowInterval(int band, int interval) {
            if (band != NAN_BAND_24GHZ && band != NAN_BAND_5GHZ) {
                throw new IllegalArgumentException("Invalid band value");
            }
            if ((band == NAN_BAND_24GHZ && (interval < 1 || interval > 5))
                    || (band == NAN_BAND_5GHZ && (interval < 0 || interval > 5))) {
                throw new IllegalArgumentException(
                        "Invalid interval value: 2.4 GHz [1,5] or 5GHz [0,5]");
            }

            mDiscoveryWindowInterval[band] = interval;
            return this;
        }

        /**
         * Build {@link ConfigRequest} given the current requests made on the
         * builder.
         */
        public ConfigRequest build() {
            if (mClusterLow > mClusterHigh) {
                throw new IllegalArgumentException(
                        "Invalid argument combination - must have Cluster Low <= Cluster High");
            }

            return new ConfigRequest(mSupport5gBand, mMasterPreference, mClusterLow, mClusterHigh,
                    mDiscoveryWindowInterval);
        }
    }
}
