/*
 * Copyright (C) 2018 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.car.drivingstate;

import static android.car.drivingstate.CarDrivingStateEvent.DRIVING_STATE_IDLING;
import static android.car.drivingstate.CarDrivingStateEvent.DRIVING_STATE_MOVING;
import static android.car.drivingstate.CarDrivingStateEvent.DRIVING_STATE_PARKED;
import static android.car.drivingstate.CarDrivingStateEvent.DRIVING_STATE_UNKNOWN;
import static android.car.drivingstate.CarUxRestrictionsManager.UX_RESTRICTION_MODE_BASELINE;
import static android.car.drivingstate.CarUxRestrictionsManager.UX_RESTRICTION_MODE_PASSENGER;

import android.annotation.FloatRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.car.drivingstate.CarDrivingStateEvent.CarDrivingState;
import android.car.drivingstate.CarUxRestrictionsManager.UxRestrictionMode;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemClock;
import android.util.ArrayMap;
import android.util.JsonReader;
import android.util.JsonWriter;
import android.util.Log;

import java.io.CharArrayWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

/**
 * Configuration for Car UX Restrictions service.
 *
 * @hide
 */
public final class CarUxRestrictionsConfiguration implements Parcelable {
    private static final String TAG = "CarUxRConfig";

    // Constants used by json de/serialization.
    private static final String JSON_NAME_MAX_CONTENT_DEPTH = "max_content_depth";
    private static final String JSON_NAME_MAX_CUMULATIVE_CONTENT_ITEMS =
            "max_cumulative_content_items";
    private static final String JSON_NAME_MAX_STRING_LENGTH = "max_string_length";
    private static final String JSON_NAME_MOVING_RESTRICTIONS = "moving_restrictions";
    private static final String JSON_NAME_IDLING_RESTRICTIONS = "idling_restrictions";
    private static final String JSON_NAME_PARKED_RESTRICTIONS = "parked_restrictions";
    private static final String JSON_NAME_UNKNOWN_RESTRICTIONS = "unknown_restrictions";
    private static final String JSON_NAME_PASSENGER_MOVING_RESTRICTIONS =
            "passenger_moving_restrictions";
    private static final String JSON_NAME_PASSENGER_IDLING_RESTRICTIONS =
            "passenger_idling_restrictions";
    private static final String JSON_NAME_PASSENGER_PARKED_RESTRICTIONS =
            "passenger_parked_restrictions";
    private static final String JSON_NAME_PASSENGER_UNKNOWN_RESTRICTIONS =
            "passenger_unknown_restrictions";
    private static final String JSON_NAME_REQ_OPT = "req_opt";
    private static final String JSON_NAME_RESTRICTIONS = "restrictions";
    private static final String JSON_NAME_SPEED_RANGE = "speed_range";
    private static final String JSON_NAME_MIN_SPEED = "min_speed";
    private static final String JSON_NAME_MAX_SPEED = "max_speed";

    private final int mMaxContentDepth;
    private final int mMaxCumulativeContentItems;
    private final int mMaxStringLength;
    private final Map<Integer, List<RestrictionsPerSpeedRange>> mPassengerUxRestrictions =
            new ArrayMap<>(DRIVING_STATES.length);
    private final Map<Integer, List<RestrictionsPerSpeedRange>> mBaselineUxRestrictions =
            new ArrayMap<>(DRIVING_STATES.length);

    private CarUxRestrictionsConfiguration(CarUxRestrictionsConfiguration.Builder builder) {
        mMaxContentDepth = builder.mMaxContentDepth;
        mMaxCumulativeContentItems = builder.mMaxCumulativeContentItems;
        mMaxStringLength = builder.mMaxStringLength;

        for (int drivingState : DRIVING_STATES) {
            List<RestrictionsPerSpeedRange> baseline = new ArrayList<>();
            for (RestrictionsPerSpeedRange r : builder.mBaselineUxRestrictions.get(drivingState)) {
                baseline.add(r);
            }
            mBaselineUxRestrictions.put(drivingState, baseline);

            List<RestrictionsPerSpeedRange> passenger = new ArrayList<>();
            for (RestrictionsPerSpeedRange r : builder.mPassengerUxRestrictions.get(drivingState)) {
                passenger.add(r);
            }
            mPassengerUxRestrictions.put(drivingState, passenger);
        }
    }

    /**
     * Returns the restrictions for
     * {@link UxRestrictionMode#UX_RESTRICTION_MODE_BASELINE}
     * based on current driving state.
     *
     * @param drivingState Driving state.
     *                     See values in {@link CarDrivingStateEvent.CarDrivingState}.
     * @param currentSpeed Current speed in meter per second.
     */
    public CarUxRestrictions getUxRestrictions(
            @CarDrivingState int drivingState, float currentSpeed) {
        return getUxRestrictions(drivingState, currentSpeed, UX_RESTRICTION_MODE_BASELINE);
    }

    /**
     * Returns the restrictions based on current driving state and restriction mode.
     *
     * <p>Restriction mode allows a different set of restrictions to be applied in the same driving
     * state. See values in {@link UxRestrictionMode}.
     *
     * @param drivingState Driving state.
     *                     See values in {@link CarDrivingStateEvent.CarDrivingState}.
     * @param currentSpeed Current speed in meter per second.
     * @param mode Current UX Restriction mode.
     */
    public CarUxRestrictions getUxRestrictions(@CarDrivingState int drivingState,
            float currentSpeed, @UxRestrictionMode int mode) {
        RestrictionsPerSpeedRange restriction = null;
        if (mode == UX_RESTRICTION_MODE_PASSENGER) {
            restriction = findUxRestrictionsInList(
                    currentSpeed, mPassengerUxRestrictions.get(drivingState));
        }
        if (restriction == null) {
            // Mode is baseline, or passenger mode does not specify restrictions for current driving
            // state.
            restriction = findUxRestrictionsInList(
                    currentSpeed, mBaselineUxRestrictions.get(drivingState));
        }

        if (restriction == null) {
            if (Build.IS_ENG || Build.IS_USERDEBUG) {
                throw new IllegalStateException("No restrictions for driving state "
                        + getDrivingStateName(drivingState));
            }
            return createDefaultUxRestrictionsEvent();
        }
        return createUxRestrictionsEvent(restriction.mReqOpt, restriction.mRestrictions);
    }

    @Nullable
    private static RestrictionsPerSpeedRange findUxRestrictionsInList(float currentSpeed,
            List<RestrictionsPerSpeedRange> restrictions) {
        if (restrictions.isEmpty()) {
            return null;
        }

        if (restrictions.size() == 1 && restrictions.get(0).mSpeedRange == null) {
            // Single restriction with no speed range implies it covers all.
            return restrictions.get(0);
        }

        for (RestrictionsPerSpeedRange r : restrictions) {
            if (r.mSpeedRange != null && r.mSpeedRange.includes(currentSpeed)) {
                return r;
            }
        }
        return null;
    }

    private CarUxRestrictions createDefaultUxRestrictionsEvent() {
        return createUxRestrictionsEvent(true,
                CarUxRestrictions.UX_RESTRICTIONS_FULLY_RESTRICTED);
    }

    /**
     * Creates CarUxRestrictions with restrictions parameters from current configuration.
     */
    private CarUxRestrictions createUxRestrictionsEvent(boolean requiresOpt,
            @CarUxRestrictions.CarUxRestrictionsInfo int uxr) {
        // In case the UXR is not baseline, set requiresDistractionOptimization to true since it
        // doesn't make sense to have an active non baseline restrictions without
        // requiresDistractionOptimization set to true.
        if (uxr != CarUxRestrictions.UX_RESTRICTIONS_BASELINE) {
            requiresOpt = true;
        }
        CarUxRestrictions.Builder builder = new CarUxRestrictions.Builder(requiresOpt, uxr,
                SystemClock.elapsedRealtimeNanos());
        if (mMaxStringLength != Builder.UX_RESTRICTIONS_UNKNOWN) {
            builder.setMaxStringLength(mMaxStringLength);
        }
        if (mMaxCumulativeContentItems != Builder.UX_RESTRICTIONS_UNKNOWN) {
            builder.setMaxCumulativeContentItems(mMaxCumulativeContentItems);
        }
        if (mMaxContentDepth != Builder.UX_RESTRICTIONS_UNKNOWN) {
            builder.setMaxContentDepth(mMaxContentDepth);
        }
        return builder.build();
    }

    // Json de/serialization methods.

    /**
     * Writes current configuration as Json.
     */
    public void writeJson(JsonWriter writer) throws IOException {
        // We need to be lenient to accept infinity number (as max speed).
        writer.setLenient(true);

        writer.beginObject();

        writer.name(JSON_NAME_MAX_CONTENT_DEPTH).value(mMaxContentDepth);
        writer.name(JSON_NAME_MAX_CUMULATIVE_CONTENT_ITEMS).value(
                mMaxCumulativeContentItems);
        writer.name(JSON_NAME_MAX_STRING_LENGTH).value(mMaxStringLength);

        writer.name(JSON_NAME_PARKED_RESTRICTIONS);
        writeRestrictionsList(writer,
                mBaselineUxRestrictions.get(DRIVING_STATE_PARKED));

        writer.name(JSON_NAME_IDLING_RESTRICTIONS);
        writeRestrictionsList(writer,
                mBaselineUxRestrictions.get(DRIVING_STATE_IDLING));

        writer.name(JSON_NAME_MOVING_RESTRICTIONS);
        writeRestrictionsList(writer,
                mBaselineUxRestrictions.get(DRIVING_STATE_MOVING));

        writer.name(JSON_NAME_UNKNOWN_RESTRICTIONS);
        writeRestrictionsList(writer,
                mBaselineUxRestrictions.get(DRIVING_STATE_UNKNOWN));

        writer.name(JSON_NAME_PASSENGER_PARKED_RESTRICTIONS);
        writeRestrictionsList(writer,
                mPassengerUxRestrictions.get(DRIVING_STATE_PARKED));

        writer.name(JSON_NAME_PASSENGER_IDLING_RESTRICTIONS);
        writeRestrictionsList(writer,
                mPassengerUxRestrictions.get(DRIVING_STATE_IDLING));

        writer.name(JSON_NAME_PASSENGER_MOVING_RESTRICTIONS);
        writeRestrictionsList(writer,
                mPassengerUxRestrictions.get(DRIVING_STATE_MOVING));

        writer.name(JSON_NAME_PASSENGER_UNKNOWN_RESTRICTIONS);
        writeRestrictionsList(writer,
                mPassengerUxRestrictions.get(DRIVING_STATE_UNKNOWN));

        writer.endObject();
    }

    private void writeRestrictionsList(JsonWriter writer, List<RestrictionsPerSpeedRange> messages)
            throws IOException {
        writer.beginArray();
        for (RestrictionsPerSpeedRange restrictions : messages) {
            writeRestrictions(writer, restrictions);
        }
        writer.endArray();
    }

    private void writeRestrictions(JsonWriter writer, RestrictionsPerSpeedRange restrictions)
            throws IOException {
        writer.beginObject();
        writer.name(JSON_NAME_REQ_OPT).value(restrictions.mReqOpt);
        writer.name(JSON_NAME_RESTRICTIONS).value(restrictions.mRestrictions);
        if (restrictions.mSpeedRange != null) {
            writer.name(JSON_NAME_SPEED_RANGE);
            writer.beginObject();
            writer.name(JSON_NAME_MIN_SPEED).value(restrictions.mSpeedRange.mMinSpeed);
            writer.name(JSON_NAME_MAX_SPEED).value(restrictions.mSpeedRange.mMaxSpeed);
            writer.endObject();
        }
        writer.endObject();
    }

    @Override
    public String toString() {
        CharArrayWriter charWriter = new CharArrayWriter();
        JsonWriter writer = new JsonWriter(charWriter);
        writer.setIndent("\t");
        try {
            writeJson(writer);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return charWriter.toString();
    }

    /**
     * Reads Json as UX restriction configuration.
     */
    public static CarUxRestrictionsConfiguration readJson(JsonReader reader) throws IOException {
        // We need to be lenient to accept infinity number (as max speed).
        reader.setLenient(true);

        Builder builder = new Builder();
        reader.beginObject();
        while (reader.hasNext()) {
            String name = reader.nextName();
            switch (name) {
                case JSON_NAME_MAX_CONTENT_DEPTH:
                    builder.setMaxContentDepth(reader.nextInt());
                    break;
                case JSON_NAME_MAX_CUMULATIVE_CONTENT_ITEMS:
                    builder.setMaxCumulativeContentItems(reader.nextInt());
                    break;
                case JSON_NAME_MAX_STRING_LENGTH:
                    builder.setMaxStringLength(reader.nextInt());
                    break;
                case JSON_NAME_PARKED_RESTRICTIONS:
                    readRestrictionsList(reader, DRIVING_STATE_PARKED,
                            UX_RESTRICTION_MODE_BASELINE, builder);
                    break;
                case JSON_NAME_IDLING_RESTRICTIONS:
                    readRestrictionsList(reader, DRIVING_STATE_IDLING,
                            UX_RESTRICTION_MODE_BASELINE, builder);
                    break;
                case JSON_NAME_MOVING_RESTRICTIONS:
                    readRestrictionsList(reader, DRIVING_STATE_MOVING,
                            UX_RESTRICTION_MODE_BASELINE, builder);
                    break;
                case JSON_NAME_UNKNOWN_RESTRICTIONS:
                    readRestrictionsList(reader, DRIVING_STATE_UNKNOWN,
                            UX_RESTRICTION_MODE_BASELINE, builder);
                    break;
                case JSON_NAME_PASSENGER_PARKED_RESTRICTIONS:
                    readRestrictionsList(reader, DRIVING_STATE_PARKED,
                            UX_RESTRICTION_MODE_PASSENGER, builder);
                    break;
                case JSON_NAME_PASSENGER_IDLING_RESTRICTIONS:
                    readRestrictionsList(reader, DRIVING_STATE_IDLING,
                            UX_RESTRICTION_MODE_PASSENGER, builder);
                    break;
                case JSON_NAME_PASSENGER_MOVING_RESTRICTIONS:
                    readRestrictionsList(reader, DRIVING_STATE_MOVING,
                            UX_RESTRICTION_MODE_PASSENGER, builder);
                    break;
                case JSON_NAME_PASSENGER_UNKNOWN_RESTRICTIONS:
                    readRestrictionsList(reader, DRIVING_STATE_UNKNOWN,
                            UX_RESTRICTION_MODE_PASSENGER, builder);
                    break;
                default:
                    Log.e(TAG, "Unknown name parsing json config: " + name);
                    reader.skipValue();
            }
        }
        reader.endObject();
        return builder.build();
    }

    private static void readRestrictionsList(JsonReader reader, @CarDrivingState int drivingState,
            @UxRestrictionMode int mode, Builder builder) throws IOException {
        reader.beginArray();
        while (reader.hasNext()) {
            DrivingStateRestrictions drivingStateRestrictions = readRestrictions(reader);
            drivingStateRestrictions.setMode(mode);

            builder.setUxRestrictions(drivingState, drivingStateRestrictions);
        }
        reader.endArray();
    }

    private static DrivingStateRestrictions readRestrictions(JsonReader reader) throws IOException {
        reader.beginObject();
        boolean reqOpt = false;
        int restrictions = CarUxRestrictions.UX_RESTRICTIONS_BASELINE;
        Builder.SpeedRange speedRange = null;
        while (reader.hasNext()) {
            String name = reader.nextName();
            if (name.equals(JSON_NAME_REQ_OPT)) {
                reqOpt = reader.nextBoolean();
            } else if (name.equals(JSON_NAME_RESTRICTIONS)) {
                restrictions = reader.nextInt();
            } else if (name.equals(JSON_NAME_SPEED_RANGE)) {
                reader.beginObject();
                // Okay to set min initial value as MAX_SPEED because SpeedRange() won't allow it.
                float minSpeed = Builder.SpeedRange.MAX_SPEED;
                float maxSpeed = Builder.SpeedRange.MAX_SPEED;

                while (reader.hasNext()) {
                    String n = reader.nextName();
                    if (n.equals(JSON_NAME_MIN_SPEED)) {
                        minSpeed = Double.valueOf(reader.nextDouble()).floatValue();
                    } else if (n.equals(JSON_NAME_MAX_SPEED)) {
                        maxSpeed = Double.valueOf(reader.nextDouble()).floatValue();
                    } else {
                        Log.e(TAG, "Unknown name parsing json config: " + n);
                        reader.skipValue();
                    }
                }
                speedRange = new Builder.SpeedRange(minSpeed, maxSpeed);
                reader.endObject();
            }
        }
        reader.endObject();
        DrivingStateRestrictions drivingStateRestrictions = new DrivingStateRestrictions()
                .setDistractionOptimizationRequired(reqOpt)
                .setRestrictions(restrictions);
        if (speedRange != null) {
            drivingStateRestrictions.setSpeedRange(speedRange);
        }
        return drivingStateRestrictions;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null || !(obj instanceof CarUxRestrictionsConfiguration)) {
            return false;
        }

        CarUxRestrictionsConfiguration other = (CarUxRestrictionsConfiguration) obj;

        // Compare UXR parameters.
        if (mMaxContentDepth != other.mMaxContentDepth
                || mMaxCumulativeContentItems != other.mMaxCumulativeContentItems
                || mMaxStringLength != other.mMaxStringLength) {
            return false;
        }

        // Compare UXR for each restriction mode.
        if (!areRestrictionsEqual(mBaselineUxRestrictions, other.mBaselineUxRestrictions)
                || !areRestrictionsEqual(
                        mPassengerUxRestrictions, other.mPassengerUxRestrictions)) {
            return false;
        }
        return true;
    }

    private boolean areRestrictionsEqual(Map<Integer, List<RestrictionsPerSpeedRange>> r1,
            Map<Integer, List<RestrictionsPerSpeedRange>> r2) {
        // Compare UXR by driving state.
        if (!r1.keySet().equals(r2.keySet())) {
            return false;
        }
        for (int drivingState : r1.keySet()) {
            List<RestrictionsPerSpeedRange> restrictions = r1.get(drivingState);
            List<RestrictionsPerSpeedRange> otherRestrictions = r2.get(drivingState);
            if (!restrictions.equals(otherRestrictions)) {
                return false;
            }
        }
        return true;
    }

    /**
     * Dump the driving state to UX restrictions mapping.
     */
    public void dump(PrintWriter writer) {
        writer.println("===========================================");
        writer.println("Baseline mode UXR:");
        writer.println("-------------------------------------------");
        dumpRestrictions(writer, mBaselineUxRestrictions);
        writer.println("Passenger mode UXR:");
        writer.println("-------------------------------------------");
        dumpRestrictions(writer, mPassengerUxRestrictions);

        writer.println("Max String length: " + mMaxStringLength);
        writer.println("Max Cumulative Content Items: " + mMaxCumulativeContentItems);
        writer.println("Max Content depth: " + mMaxContentDepth);
        writer.println("===========================================");
    }

    private void dumpRestrictions(
            PrintWriter writer, Map<Integer, List<RestrictionsPerSpeedRange>> restrictions) {
        for (Integer state : restrictions.keySet()) {
            List<RestrictionsPerSpeedRange> list = restrictions.get(state);
            writer.println("State:" + getDrivingStateName(state)
                    + " num restrictions:" + list.size());
            for (RestrictionsPerSpeedRange r : list) {
                writer.println("Requires DO? " + r.mReqOpt
                        + "\nRestrictions: 0x" + Integer.toHexString(r.mRestrictions)
                        + "\nSpeed Range: "
                        + (r.mSpeedRange == null
                        ? "None"
                        : (r.mSpeedRange.mMinSpeed + " - " + r.mSpeedRange.mMaxSpeed)));
                writer.println("-------------------------------------------");
            }
        }
    }

    private static String getDrivingStateName(@CarDrivingState int state) {
        switch (state) {
            case DRIVING_STATE_PARKED:
                return "parked";
            case DRIVING_STATE_IDLING:
                return "idling";
            case DRIVING_STATE_MOVING:
                return "moving";
            case DRIVING_STATE_UNKNOWN:
                return "unknown";
            default:
                throw new IllegalArgumentException("Unrecognized state value: " + state);
        }
    }

    // Parcelable methods/fields.

    // Used by Parcel methods to ensure de/serialization order.
    private static final int[] DRIVING_STATES = new int[] {
            DRIVING_STATE_UNKNOWN,
            DRIVING_STATE_PARKED,
            DRIVING_STATE_IDLING,
            DRIVING_STATE_MOVING,
    };

    public static final Parcelable.Creator<CarUxRestrictionsConfiguration> CREATOR =
            new Parcelable.Creator<CarUxRestrictionsConfiguration>() {

        @Override
        public CarUxRestrictionsConfiguration createFromParcel(Parcel source) {
            return new CarUxRestrictionsConfiguration(source);
        }

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

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

    private CarUxRestrictionsConfiguration(Parcel in) {
        for (int drivingState : DRIVING_STATES) {
            List<RestrictionsPerSpeedRange> restrictions = new ArrayList<>();
            in.readTypedList(restrictions, RestrictionsPerSpeedRange.CREATOR);
            mBaselineUxRestrictions.put(drivingState, restrictions);
        }
        for (int drivingState : DRIVING_STATES) {
            List<RestrictionsPerSpeedRange> restrictions = new ArrayList<>();
            in.readTypedList(restrictions, RestrictionsPerSpeedRange.CREATOR);
            mPassengerUxRestrictions.put(drivingState, restrictions);
        }
        mMaxContentDepth = in.readInt();
        mMaxCumulativeContentItems = in.readInt();
        mMaxStringLength = in.readInt();
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        for (int drivingState : DRIVING_STATES) {
            dest.writeTypedList(mBaselineUxRestrictions.get(drivingState));
        }
        for (int drivingState : DRIVING_STATES) {
            dest.writeTypedList(mPassengerUxRestrictions.get(drivingState));
        }
        dest.writeInt(mMaxContentDepth);
        dest.writeInt(mMaxCumulativeContentItems);
        dest.writeInt(mMaxStringLength);
    }

    /**
     * @hide
     */
    public static final class Builder {

        private static final int UX_RESTRICTIONS_UNKNOWN = -1;

        private int mMaxContentDepth = UX_RESTRICTIONS_UNKNOWN;
        private int mMaxCumulativeContentItems = UX_RESTRICTIONS_UNKNOWN;
        private int mMaxStringLength = UX_RESTRICTIONS_UNKNOWN;

        public Map<Integer, List<RestrictionsPerSpeedRange>> mPassengerUxRestrictions =
                new ArrayMap<>(DRIVING_STATES.length);
        public Map<Integer, List<RestrictionsPerSpeedRange>> mBaselineUxRestrictions =
                new ArrayMap<>(DRIVING_STATES.length);

        public Builder() {
            for (int drivingState : DRIVING_STATES) {
                mBaselineUxRestrictions.put(drivingState, new ArrayList<>());
                mPassengerUxRestrictions.put(drivingState, new ArrayList<>());
            }
        }

        /**
         * Sets UX restrictions for driving state.
         */
        public Builder setUxRestrictions(@CarDrivingState int drivingState,
                boolean requiresOptimization,
                @CarUxRestrictions.CarUxRestrictionsInfo int restrictions) {
            return this.setUxRestrictions(drivingState, new DrivingStateRestrictions()
                    .setDistractionOptimizationRequired(requiresOptimization)
                    .setRestrictions(restrictions));
        }

        /**
         * Sets UX restrictions with speed range.
         *
         * @param drivingState Restrictions will be set for this Driving state.
         *                     See constants in {@link CarDrivingStateEvent}.
         * @param speedRange If set, restrictions will only apply when current speed is within
         *                   the range. Only {@link CarDrivingStateEvent#DRIVING_STATE_MOVING}
         *                   supports speed range. {@code null} implies the full speed range,
         *                   i.e. zero to {@link SpeedRange#MAX_SPEED}.
         * @param requiresOptimization Whether distraction optimization (DO) is required for this
         *                             driving state.
         * @param restrictions See constants in {@link CarUxRestrictions}.
         *
         * @deprecated Use {@link #setUxRestrictions(int, DrivingStateRestrictions)} instead.
         */
        @Deprecated
        public Builder setUxRestrictions(@CarDrivingState int drivingState,
                @NonNull SpeedRange speedRange, boolean requiresOptimization,
                @CarUxRestrictions.CarUxRestrictionsInfo int restrictions) {
            return setUxRestrictions(drivingState, new DrivingStateRestrictions()
                    .setDistractionOptimizationRequired(requiresOptimization)
                    .setRestrictions(restrictions)
                    .setSpeedRange(speedRange));
        }

        /**
         * Sets UX restriction.
         *
         * @param drivingState Restrictions will be set for this Driving state.
         *                     See constants in {@link CarDrivingStateEvent}.
         * @param drivingStateRestrictions Restrictions to set.
         *
         * @return This builder object for method chaining.
         */
        public Builder setUxRestrictions(
                int drivingState, DrivingStateRestrictions drivingStateRestrictions) {
            SpeedRange speedRange = drivingStateRestrictions.mSpeedRange;

            if (drivingState != DRIVING_STATE_MOVING && speedRange != null) {
                throw new IllegalArgumentException(
                        "Non-moving driving state should not specify speed range.");
            }

            List<RestrictionsPerSpeedRange> restrictions;
            switch (drivingStateRestrictions.mMode) {
                case UX_RESTRICTION_MODE_BASELINE:
                    restrictions = mBaselineUxRestrictions.get(drivingState);
                    break;
                case UX_RESTRICTION_MODE_PASSENGER:
                    restrictions = mPassengerUxRestrictions.get(drivingState);
                    break;
                default:
                    String mode = CarUxRestrictionsManager.modeToString(
                            drivingStateRestrictions.mMode);
                    throw new IllegalArgumentException("Unrecognized restriction mode " + mode);
            }
            restrictions.add(new RestrictionsPerSpeedRange(
                    drivingStateRestrictions.mMode, drivingStateRestrictions.mReqOpt,
                    drivingStateRestrictions.mRestrictions, speedRange));
            return this;
        }


        /**
         * Sets max string length.
         */
        public Builder setMaxStringLength(int maxStringLength) {
            mMaxStringLength = maxStringLength;
            return this;
        }

        /**
         * Sets max cumulative content items.
         */
        public Builder setMaxCumulativeContentItems(int maxCumulativeContentItems) {
            mMaxCumulativeContentItems = maxCumulativeContentItems;
            return this;
        }

        /**
         * Sets max content depth.
         */
        public Builder setMaxContentDepth(int maxContentDepth) {
            mMaxContentDepth = maxContentDepth;
            return this;
        }

        /**
         * @return CarUxRestrictionsConfiguration based on builder configuration.
         */
        public CarUxRestrictionsConfiguration build() {
            // Unspecified driving state should be fully restricted to be safe.
            addDefaultRestrictionsToBaseline();

            validateBaselineModeRestrictions();
            validatePassengerModeRestrictions();

            return new CarUxRestrictionsConfiguration(this);
        }

        private void addDefaultRestrictionsToBaseline() {
            for (int drivingState : DRIVING_STATES) {
                List<RestrictionsPerSpeedRange> restrictions =
                        mBaselineUxRestrictions.get(drivingState);
                if (restrictions.size() == 0) {
                    Log.i(TAG, "Using default restrictions for driving state: "
                            + getDrivingStateName(drivingState));
                    restrictions.add(new RestrictionsPerSpeedRange(
                            true, CarUxRestrictions.UX_RESTRICTIONS_FULLY_RESTRICTED));
                }
            }
        }

        private void validateBaselineModeRestrictions() {
            for (int drivingState : DRIVING_STATES) {
                List<RestrictionsPerSpeedRange> restrictions =
                        mBaselineUxRestrictions.get(drivingState);
                if (drivingState != DRIVING_STATE_MOVING) {
                    // Note: For non-moving state, setUxRestrictions() rejects UxRestriction with
                    // speed range, so we don't check here.
                    if (restrictions.size() != 1) {
                        throw new IllegalStateException("Non-moving driving state should "
                                + "contain one set of restriction rules.");
                    }
                }

                // If there are multiple restrictions, each one should specify speed range.
                if (restrictions.size() > 1 && restrictions.stream().anyMatch(
                        restriction -> restriction.mSpeedRange == null)) {
                    StringBuilder error = new StringBuilder();
                    for (RestrictionsPerSpeedRange restriction : restrictions) {
                        error.append(restriction.toString()).append('\n');
                    }
                    throw new IllegalStateException(
                            "Every restriction in MOVING state should contain driving state.\n"
                                    + error.toString());
                }

                // Sort restrictions based on speed range.
                Collections.sort(restrictions,
                        Comparator.comparing(RestrictionsPerSpeedRange::getSpeedRange));

                validateRangeOfSpeed(restrictions);
                validateContinuousSpeedRange(restrictions);
            }
        }

        private void validatePassengerModeRestrictions() {
            List<RestrictionsPerSpeedRange> passengerMovingRestrictions =
                    mPassengerUxRestrictions.get(DRIVING_STATE_MOVING);
            Collections.sort(passengerMovingRestrictions,
                    Comparator.comparing(RestrictionsPerSpeedRange::getSpeedRange));

            validateContinuousSpeedRange(passengerMovingRestrictions);
        }

        /**
         * Validates if combined speed ranges of given restrictions.
         *
         * <p>Restrictions are considered to contain valid speed ranges if:
         * <ul>
         * <li>None contains a speed range - implies full range; or
         * <li>Combination covers range [0 - MAX_SPEED]
         * </ul>
         *
         * Throws exception on invalidate input.
         *
         * @param restrictions Restrictions to be checked. Must be sorted.
         */
        private void validateRangeOfSpeed(List<RestrictionsPerSpeedRange> restrictions) {
            if (restrictions.size() == 1) {
                SpeedRange speedRange = restrictions.get(0).mSpeedRange;
                if (speedRange == null) {
                    // Single restriction with null speed range implies that
                    // it applies to the entire driving state.
                    return;
                }
            }
            if (Float.compare(restrictions.get(0).mSpeedRange.mMinSpeed, 0) != 0) {
                throw new IllegalStateException(
                        "Speed range min speed should start at 0.");
            }
            float lastMaxSpeed = restrictions.get(restrictions.size() - 1).mSpeedRange.mMaxSpeed;
            if (Float.compare(lastMaxSpeed, SpeedRange.MAX_SPEED) != 0) {
                throw new IllegalStateException(
                        "Max speed of last restriction should be MAX_SPEED.");
            }
        }

        /**
         * Validates if combined speed ranges of given restrictions are continuous, meaning they:
         * <ul>
         * <li>Do not overlap; and
         * <li>Do not contain gap
         * </ul>
         *
         * <p>Namely the max speed of current range equals the min speed of next range.
         *
         * Throws exception on invalidate input.
         *
         * @param restrictions Restrictions to be checked. Must be sorted.
         */
        private void validateContinuousSpeedRange(List<RestrictionsPerSpeedRange> restrictions) {
            for (int i = 1; i < restrictions.size(); i++) {
                RestrictionsPerSpeedRange prev = restrictions.get(i - 1);
                RestrictionsPerSpeedRange curr = restrictions.get(i);
                // If current min != prev.max, there's either an overlap or a gap in speed range.
                if (Float.compare(curr.mSpeedRange.mMinSpeed, prev.mSpeedRange.mMaxSpeed) != 0) {
                    throw new IllegalArgumentException(
                            "Mis-configured speed range. Possibly speed range overlap or gap.");
                }
            }
        }

        /**
         * Speed range is defined by min and max speed. When there is no upper bound for max speed,
         * set it to {@link SpeedRange#MAX_SPEED}.
         */
        public static final class SpeedRange implements Comparable<SpeedRange> {
            public static final float MAX_SPEED = Float.POSITIVE_INFINITY;

            private float mMinSpeed;
            private float mMaxSpeed;

            /**
             * Defaults max speed to {@link SpeedRange#MAX_SPEED}.
             */
            public SpeedRange(@FloatRange(from = 0.0) float minSpeed) {
                this(minSpeed, MAX_SPEED);
            }

            public SpeedRange(@FloatRange(from = 0.0) float minSpeed,
                    @FloatRange(from = 0.0) float maxSpeed) {
                if (minSpeed == MAX_SPEED) {
                    throw new IllegalArgumentException("Min speed cannot be MAX_SPEED.");
                }
                if (minSpeed > maxSpeed) {
                    throw new IllegalArgumentException("Min speed " + minSpeed
                            + " should not be greater than max speed " + maxSpeed);
                }
                mMinSpeed = minSpeed;
                mMaxSpeed = maxSpeed;
            }

             /**
             * Return if the given speed is in the range of [minSpeed, maxSpeed).
             *
             * @param speed Speed to check
             * @return {@code true} if in range; {@code false} otherwise.
             */
            public boolean includes(float speed) {
                return mMinSpeed <= speed && speed < mMaxSpeed;
            }

            @Override
            public int compareTo(SpeedRange other) {
                // First compare min speed; then max speed.
                int minSpeedComparison = Float.compare(this.mMinSpeed, other.mMinSpeed);
                if (minSpeedComparison != 0) {
                    return minSpeedComparison;
                }

                return Float.compare(this.mMaxSpeed, other.mMaxSpeed);
            }

            @Override
            public boolean equals(Object obj) {
                if (this == obj) {
                    return true;
                }
                if (obj == null || !(obj instanceof SpeedRange)) {
                    return false;
                }
                SpeedRange other = (SpeedRange) obj;

                return this.compareTo(other) == 0;
            }

            @Override
            public String toString() {
                return new StringBuilder()
                        .append("[min: ").append(mMinSpeed)
                        .append("; max: ").append(mMaxSpeed == MAX_SPEED ? "max_speed" : mMaxSpeed)
                        .append("]")
                        .toString();
            }
        }
    }

    /**
     * UX restrictions to be applied to a driving state through {@link
     * Builder#setUxRestrictions(int, CarUxRestrictionsConfiguration.DrivingStateRestrictions)}.
     * These UX restrictions can also specified to be only applicable to certain speed range and
     * restriction mode.
     *
     * @see UxRestrictionMode
     * @see Builder.SpeedRange
     *
     * @hide
     */
    public static final class DrivingStateRestrictions {
        private int mMode = UX_RESTRICTION_MODE_BASELINE;
        private boolean mReqOpt = true;
        private int mRestrictions = CarUxRestrictions.UX_RESTRICTIONS_FULLY_RESTRICTED;
        @Nullable private Builder.SpeedRange mSpeedRange;

        /**
         * Sets whether Distraction Optimization (DO) is required. Defaults to {@code true}.
         */
        public DrivingStateRestrictions setDistractionOptimizationRequired(
                boolean distractionOptimizationRequired) {
            mReqOpt = distractionOptimizationRequired;
            return this;
        }

        /**
         * Sets active restrictions.
         * Defaults to {@link CarUxRestrictions#UX_RESTRICTIONS_FULLY_RESTRICTED}.
         */
        public DrivingStateRestrictions setRestrictions(
                @CarUxRestrictions.CarUxRestrictionsInfo int restrictions) {
            mRestrictions = restrictions;
            return this;
        }

        /**
         * Sets restriction mode to apply to.
         * Defaults to {@link CarUxRestrictionsManager#UX_RESTRICTION_MODE_BASELINE}.
         */
        public DrivingStateRestrictions setMode(@UxRestrictionMode int mode) {
            mMode = mode;
            return this;
        }

        /**
         * Sets speed range to apply to. Optional value. Not setting one means the restrictions
         * apply to full speed range, namely {@code 0} to {@link Builder.SpeedRange#MAX_SPEED}.
         */
        public DrivingStateRestrictions setSpeedRange(@NonNull Builder.SpeedRange speedRange) {
            mSpeedRange = speedRange;
            return this;
        }

        @Override
        public String toString() {
            return new StringBuilder()
                    .append("Mode: ").append(CarUxRestrictionsManager.modeToString(mMode))
                    .append(". Requires DO? ").append(mReqOpt)
                    .append(". Restrictions: ").append(Integer.toBinaryString(mRestrictions))
                    .append(". SpeedRange: ")
                    .append(mSpeedRange == null ? "null" : mSpeedRange.toString())
                    .toString();
        }
    }

    /**
     * Container for UX restrictions for a speed range.
     * Speed range is valid only for the {@link CarDrivingStateEvent#DRIVING_STATE_MOVING}.
     */
    private static final class RestrictionsPerSpeedRange implements Parcelable {
        @UxRestrictionMode
        final int mMode;
        final boolean mReqOpt;
        final int mRestrictions;
        @Nullable
        final Builder.SpeedRange mSpeedRange;

        RestrictionsPerSpeedRange(boolean reqOpt, int restrictions) {
            this(UX_RESTRICTION_MODE_BASELINE, reqOpt, restrictions, null);
        }

        RestrictionsPerSpeedRange(@UxRestrictionMode int mode, boolean reqOpt, int restrictions,
                @Nullable Builder.SpeedRange speedRange) {
            if (!reqOpt && restrictions != CarUxRestrictions.UX_RESTRICTIONS_BASELINE) {
                throw new IllegalArgumentException(
                        "Driving optimization is not required but UX restrictions is required.");
            }
            mMode = mode;
            mReqOpt = reqOpt;
            mRestrictions = restrictions;
            mSpeedRange = speedRange;
        }

        public Builder.SpeedRange getSpeedRange() {
            return mSpeedRange;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (obj == null || !(obj instanceof RestrictionsPerSpeedRange)) {
                return false;
            }
            RestrictionsPerSpeedRange other = (RestrictionsPerSpeedRange) obj;
            return mMode == other.mMode
                    && mReqOpt == other.mReqOpt
                    && mRestrictions == other.mRestrictions
                    && ((mSpeedRange == null && other.mSpeedRange == null) || mSpeedRange.equals(
                    other.mSpeedRange));
        }

        @Override
        public String toString() {
            return new StringBuilder()
                    .append("[Mode is ").append(CarUxRestrictionsManager.modeToString(mMode))
                    .append("; Requires DO? ").append(mReqOpt)
                    .append("; Restrictions: ").append(Integer.toBinaryString(mRestrictions))
                    .append("; Speed range: ")
                    .append(mSpeedRange == null ? "null" : mSpeedRange.toString())
                    .append(']')
                    .toString();
        }

        // Parcelable methods/fields.

        public static final Creator<RestrictionsPerSpeedRange> CREATOR =
                new Creator<RestrictionsPerSpeedRange>() {
                    @Override
                    public RestrictionsPerSpeedRange createFromParcel(Parcel in) {
                        return new RestrictionsPerSpeedRange(in);
                    }

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

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

        protected RestrictionsPerSpeedRange(Parcel in) {
            mMode = in.readInt();
            mReqOpt = in.readBoolean();
            mRestrictions = in.readInt();
            // Whether speed range is specified.
            Builder.SpeedRange speedRange = null;
            if (in.readBoolean()) {
                float minSpeed = in.readFloat();
                float maxSpeed = in.readFloat();
                speedRange = new Builder.SpeedRange(minSpeed, maxSpeed);
            }
            mSpeedRange = speedRange;
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeInt(mMode);
            dest.writeBoolean(mReqOpt);
            dest.writeInt(mRestrictions);
            // Whether speed range is specified.
            dest.writeBoolean(mSpeedRange != null);
            if (mSpeedRange != null) {
                dest.writeFloat(mSpeedRange.mMinSpeed);
                dest.writeFloat(mSpeedRange.mMaxSpeed);
            }
        }
    }
}
