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

import android.annotation.ArrayRes;
import android.os.Parcel;
import android.os.Parcelable;

import java.util.Arrays;
import java.util.Objects;

/**
 * Applications can expose restrictions for a restricted user on a
 * multiuser device. The administrator can configure these restrictions that will then be
 * applied to the restricted user. Each RestrictionsEntry is one configurable restriction.
 * <p/>
 * Any application that chooses to expose such restrictions does so by implementing a
 * receiver that handles the {@link Intent#ACTION_GET_RESTRICTION_ENTRIES} action.
 * The receiver then returns a result bundle that contains an entry called "restrictions", whose
 * value is an ArrayList<RestrictionsEntry>.
 */
public class RestrictionEntry implements Parcelable {

    /**
     * Hidden restriction type. Use this type for information that needs to be transferred
     * across but shouldn't be presented to the user in the UI. Stores a single String value.
     */
    public static final int TYPE_NULL         = 0;

    /**
     * Restriction of type "bool". Use this for storing a boolean value, typically presented as
     * a checkbox in the UI.
     */
    public static final int TYPE_BOOLEAN      = 1;

    /**
     * Restriction of type "choice". Use this for storing a string value, typically presented as
     * a single-select list. Call {@link #setChoiceEntries(String[])} and
     * {@link #setChoiceValues(String[])} to set the localized list entries to present to the user
     * and the corresponding values, respectively.
     */
    public static final int TYPE_CHOICE       = 2;

    /**
     * Internal restriction type. Use this for storing a string value, typically presented as
     * a single-select list. Call {@link #setChoiceEntries(String[])} and
     * {@link #setChoiceValues(String[])} to set the localized list entries to present to the user
     * and the corresponding values, respectively.
     * The presentation could imply that values in lower array indices are included when a
     * particular value is chosen.
     * @hide
     */
    public static final int TYPE_CHOICE_LEVEL = 3;

    /**
     * Restriction of type "multi-select". Use this for presenting a multi-select list where more
     * than one entry can be selected, such as for choosing specific titles to white-list.
     * Call {@link #setChoiceEntries(String[])} and
     * {@link #setChoiceValues(String[])} to set the localized list entries to present to the user
     * and the corresponding values, respectively.
     * Use {@link #getAllSelectedStrings()} and {@link #setAllSelectedStrings(String[])} to
     * manipulate the selections.
     */
    public static final int TYPE_MULTI_SELECT = 4;

    /**
     * Restriction of type "integer". Use this for storing an integer value. The range of values
     * is from {@link Integer#MIN_VALUE} to {@link Integer#MAX_VALUE}.
     */
    public static final int TYPE_INTEGER = 5;

    /**
     * Restriction of type "string". Use this for storing a string value.
     * @see #setSelectedString
     * @see #getSelectedString
     */
    public static final int TYPE_STRING = 6;

    /**
     * Restriction of type "bundle". Use this for storing {@link android.os.Bundle bundles} of
     * restrictions
     */
    public static final int TYPE_BUNDLE = 7;

    /**
     * Restriction of type "bundle_array". Use this for storing arrays of
     * {@link android.os.Bundle bundles} of restrictions
     */
    public static final int TYPE_BUNDLE_ARRAY = 8;

    /** The type of restriction. */
    private int mType;

    /** The unique key that identifies the restriction. */
    private String mKey;

    /** The user-visible title of the restriction. */
    private String mTitle;

    /** The user-visible secondary description of the restriction. */
    private String mDescription;

    /** The user-visible set of choices used for single-select and multi-select lists. */
    private String[] mChoiceEntries;

    /** The values corresponding to the user-visible choices. The value(s) of this entry will
     * one or more of these, returned by {@link #getAllSelectedStrings()} and
     * {@link #getSelectedString()}.
     */
    private String[] mChoiceValues;

    /* The chosen value, whose content depends on the type of the restriction. */
    private String mCurrentValue;

    /* List of selected choices in the multi-select case. */
    private String[] mCurrentValues;

    /**
     * List of nested restrictions. Used by {@link #TYPE_BUNDLE bundle} and
     * {@link #TYPE_BUNDLE_ARRAY bundle_array} restrictions.
     */
    private RestrictionEntry[] mRestrictions;

    /**
     * Constructor for specifying the type and key, with no initial value;
     *
     * @param type the restriction type.
     * @param key the unique key for this restriction
     */
    public RestrictionEntry(int type, String key) {
        mType = type;
        mKey = key;
    }

    /**
     * Constructor for {@link #TYPE_CHOICE} type.
     * @param key the unique key for this restriction
     * @param selectedString the current value
     */
    public RestrictionEntry(String key, String selectedString) {
        this.mKey = key;
        this.mType = TYPE_CHOICE;
        this.mCurrentValue = selectedString;
    }

    /**
     * Constructor for {@link #TYPE_BOOLEAN} type.
     * @param key the unique key for this restriction
     * @param selectedState whether this restriction is selected or not
     */
    public RestrictionEntry(String key, boolean selectedState) {
        this.mKey = key;
        this.mType = TYPE_BOOLEAN;
        setSelectedState(selectedState);
    }

    /**
     * Constructor for {@link #TYPE_MULTI_SELECT} type.
     * @param key the unique key for this restriction
     * @param selectedStrings the list of values that are currently selected
     */
    public RestrictionEntry(String key, String[] selectedStrings) {
        this.mKey = key;
        this.mType = TYPE_MULTI_SELECT;
        this.mCurrentValues = selectedStrings;
    }

    /**
     * Constructor for {@link #TYPE_INTEGER} type.
     * @param key the unique key for this restriction
     * @param selectedInt the integer value of the restriction
     */
    public RestrictionEntry(String key, int selectedInt) {
        mKey = key;
        mType = TYPE_INTEGER;
        setIntValue(selectedInt);
    }

    /**
     * Constructor for {@link #TYPE_BUNDLE}/{@link #TYPE_BUNDLE_ARRAY} type.
     * @param key the unique key for this restriction
     * @param restrictionEntries array of nested restriction entries. If the entry, being created
     * represents a {@link #TYPE_BUNDLE_ARRAY bundle-array}, {@code restrictionEntries} array may
     * only contain elements of type {@link #TYPE_BUNDLE bundle}.
     * @param isBundleArray true if this restriction represents
     * {@link #TYPE_BUNDLE_ARRAY bundle-array} type, otherwise the type will be set to
     * {@link #TYPE_BUNDLE bundle}.
     */
    private RestrictionEntry(String key, RestrictionEntry[] restrictionEntries,
            boolean isBundleArray) {
        mKey = key;
        if (isBundleArray) {
            mType = TYPE_BUNDLE_ARRAY;
            if (restrictionEntries != null) {
                for (RestrictionEntry restriction : restrictionEntries) {
                    if (restriction.getType() != TYPE_BUNDLE) {
                        throw new IllegalArgumentException("bundle_array restriction can only have "
                                + "nested restriction entries of type bundle");
                    }
                }
            }
        } else {
            mType = TYPE_BUNDLE;
        }
        setRestrictions(restrictionEntries);
    }

    /**
     * Creates an entry of type {@link #TYPE_BUNDLE}.
     * @param key the unique key for this restriction
     * @param restrictionEntries array of nested restriction entries.
     * @return the newly created restriction
     */
    public static RestrictionEntry createBundleEntry(String key,
            RestrictionEntry[] restrictionEntries) {
        return new RestrictionEntry(key, restrictionEntries, false);
    }

    /**
     * Creates an entry of type {@link #TYPE_BUNDLE_ARRAY}.
     * @param key the unique key for this restriction
     * @param restrictionEntries array of nested restriction entries. The array may only contain
     * elements of type {@link #TYPE_BUNDLE bundle}.
     * @return the newly created restriction
     */
    public static RestrictionEntry createBundleArrayEntry(String key,
            RestrictionEntry[] restrictionEntries) {
        return new RestrictionEntry(key, restrictionEntries, true);
    }

    /**
     * Sets the type for this restriction.
     * @param type the type for this restriction.
     */
    public void setType(int type) {
        this.mType = type;
    }

    /**
     * Returns the type for this restriction.
     * @return the type for this restriction
     */
    public int getType() {
        return mType;
    }

    /**
     * Returns the currently selected string value.
     * @return the currently selected value, which can be null for types that aren't for holding
     * single string values.
     */
    public String getSelectedString() {
        return mCurrentValue;
    }

    /**
     * Returns the list of currently selected values.
     * @return the list of current selections, if type is {@link #TYPE_MULTI_SELECT},
     *  null otherwise.
     */
    public String[] getAllSelectedStrings() {
        return mCurrentValues;
    }

    /**
     * Returns the current selected state for an entry of type {@link #TYPE_BOOLEAN}.
     * @return the current selected state of the entry.
     */
    public boolean getSelectedState() {
        return Boolean.parseBoolean(mCurrentValue);
    }

    /**
     * Returns the value of the entry as an integer when the type is {@link #TYPE_INTEGER}.
     * @return the integer value of the entry.
     */
    public int getIntValue() {
        return Integer.parseInt(mCurrentValue);
    }

    /**
     * Sets the integer value of the entry when the type is {@link #TYPE_INTEGER}.
     * @param value the integer value to set.
     */
    public void setIntValue(int value) {
        mCurrentValue = Integer.toString(value);
    }

    /**
     * Sets the string value to use as the selected value for this restriction. This value will
     * be persisted by the system for later use by the application.
     * @param selectedString the string value to select.
     */
    public void setSelectedString(String selectedString) {
        mCurrentValue = selectedString;
    }

    /**
     * Sets the current selected state for an entry of type {@link #TYPE_BOOLEAN}. This value will
     * be persisted by the system for later use by the application.
     * @param state the current selected state
     */
    public void setSelectedState(boolean state) {
        mCurrentValue = Boolean.toString(state);
    }

    /**
     * Sets the current list of selected values for an entry of type {@link #TYPE_MULTI_SELECT}.
     * These values will be persisted by the system for later use by the application.
     * @param allSelectedStrings the current list of selected values.
     */
    public void setAllSelectedStrings(String[] allSelectedStrings) {
        mCurrentValues = allSelectedStrings;
    }

    /**
     * Sets a list of string values that can be selected by the user. If no user-visible entries
     * are set by a call to {@link #setChoiceEntries(String[])}, these values will be the ones
     * shown to the user. Values will be chosen from this list as the user's selection and the
     * selected values can be retrieved by a call to {@link #getAllSelectedStrings()}, or
     * {@link #getSelectedString()}, depending on whether it is a multi-select type or choice type.
     * This method is not relevant for types other than
     * {@link #TYPE_CHOICE}, and {@link #TYPE_MULTI_SELECT}.
     * @param choiceValues an array of Strings which will be the selected values for the user's
     * selections.
     * @see #getChoiceValues()
     * @see #getAllSelectedStrings()
     */
    public void setChoiceValues(String[] choiceValues) {
        mChoiceValues = choiceValues;
    }

    /**
     * Sets a list of string values that can be selected by the user, similar to
     * {@link #setChoiceValues(String[])}.
     * @param context the application context for retrieving the resources.
     * @param stringArrayResId the resource id for a string array containing the possible values.
     * @see #setChoiceValues(String[])
     */
    public void setChoiceValues(Context context, @ArrayRes int stringArrayResId) {
        mChoiceValues = context.getResources().getStringArray(stringArrayResId);
    }

    /**
     * Returns array of possible restriction entries that this entry may contain.
     */
    public RestrictionEntry[] getRestrictions() {
        return mRestrictions;
    }

   /**
    * Sets an array of possible restriction entries, that this entry may contain.
    * <p>This method is only relevant for types {@link #TYPE_BUNDLE} and
    * {@link #TYPE_BUNDLE_ARRAY}
    */
    public void setRestrictions(RestrictionEntry[] restrictions) {
        mRestrictions = restrictions;
    }

    /**
     * Returns the list of possible string values set earlier.
     * @return the list of possible values.
     */
    public String[] getChoiceValues() {
        return mChoiceValues;
    }

    /**
     * Sets a list of strings that will be presented as choices to the user. When the
     * user selects one or more of these choices, the corresponding value from the possible values
     * are stored as the selected strings. The size of this array must match the size of the array
     * set in {@link #setChoiceValues(String[])}. This method is not relevant for types other
     * than {@link #TYPE_CHOICE}, and {@link #TYPE_MULTI_SELECT}.
     * @param choiceEntries the list of user-visible choices.
     * @see #setChoiceValues(String[])
     */
    public void setChoiceEntries(String[] choiceEntries) {
        mChoiceEntries = choiceEntries;
    }

    /** Sets a list of strings that will be presented as choices to the user. This is similar to
     * {@link #setChoiceEntries(String[])}.
     * @param context the application context, used for retrieving the resources.
     * @param stringArrayResId the resource id of a string array containing the possible entries.
     */
    public void setChoiceEntries(Context context, @ArrayRes int stringArrayResId) {
        mChoiceEntries = context.getResources().getStringArray(stringArrayResId);
    }

    /**
     * Returns the list of strings, set earlier, that will be presented as choices to the user.
     * @return the list of choices presented to the user.
     */
    public String[] getChoiceEntries() {
        return mChoiceEntries;
    }

    /**
     * Returns the provided user-visible description of the entry, if any.
     * @return the user-visible description, null if none was set earlier.
     */
    public String getDescription() {
        return mDescription;
    }

    /**
     * Sets the user-visible description of the entry, as a possible sub-text for the title.
     * You can use this to describe the entry in more detail or to display the current state of
     * the restriction.
     * @param description the user-visible description string.
     */
    public void setDescription(String description) {
        this.mDescription = description;
    }

    /**
     * This is the unique key for the restriction entry.
     * @return the key for the restriction.
     */
    public String getKey() {
        return mKey;
    }

    /**
     * Returns the user-visible title for the entry, if any.
     * @return the user-visible title for the entry, null if none was set earlier.
     */
    public String getTitle() {
        return mTitle;
    }

    /**
     * Sets the user-visible title for the entry.
     * @param title the user-visible title for the entry.
     */
    public void setTitle(String title) {
        this.mTitle = title;
    }

    @Override
    public boolean equals(Object o) {
        if (o == this) return true;
        if (!(o instanceof RestrictionEntry)) return false;
        final RestrictionEntry other = (RestrictionEntry) o;
        if (mType != other.mType || !mKey.equals(other.mKey)) {
            return false;
        }
        if (mCurrentValues == null && other.mCurrentValues == null
                && mRestrictions == null && other.mRestrictions == null
                && Objects.equals(mCurrentValue, other.mCurrentValue)) {
            return true;
        }
        if (mCurrentValue == null && other.mCurrentValue == null
                && mRestrictions == null && other.mRestrictions == null
                && Arrays.equals(mCurrentValues, other.mCurrentValues)) {
            return true;
        }
        if (mCurrentValue == null && other.mCurrentValue == null
                && mCurrentValue == null && other.mCurrentValue == null
                && Arrays.equals(mRestrictions, other.mRestrictions)) {
            return true;
        }
        return false;
    }

    @Override
    public int hashCode() {
        int result = 17;
        result = 31 * result + mKey.hashCode();
        if (mCurrentValue != null) {
            result = 31 * result + mCurrentValue.hashCode();
        } else if (mCurrentValues != null) {
            for (String value : mCurrentValues) {
                if (value != null) {
                    result = 31 * result + value.hashCode();
                }
            }
        } else if (mRestrictions != null) {
            result = 31 * result + Arrays.hashCode(mRestrictions);
        }
        return result;
    }

    public RestrictionEntry(Parcel in) {
        mType = in.readInt();
        mKey = in.readString();
        mTitle = in.readString();
        mDescription = in.readString();
        mChoiceEntries = in.readStringArray();
        mChoiceValues = in.readStringArray();
        mCurrentValue = in.readString();
        mCurrentValues = in.readStringArray();
        Parcelable[] parcelables = in.readParcelableArray(null);
        if (parcelables != null) {
            mRestrictions = new RestrictionEntry[parcelables.length];
            for (int i = 0; i < parcelables.length; i++) {
                mRestrictions[i] = (RestrictionEntry) parcelables[i];
            }
        }
    }

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(mType);
        dest.writeString(mKey);
        dest.writeString(mTitle);
        dest.writeString(mDescription);
        dest.writeStringArray(mChoiceEntries);
        dest.writeStringArray(mChoiceValues);
        dest.writeString(mCurrentValue);
        dest.writeStringArray(mCurrentValues);
        dest.writeParcelableArray(mRestrictions, 0);
    }

    public static final @android.annotation.NonNull Creator<RestrictionEntry> CREATOR = new Creator<RestrictionEntry>() {
        public RestrictionEntry createFromParcel(Parcel source) {
            return new RestrictionEntry(source);
        }

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

    @Override
    public String toString() {
        return "RestrictionEntry{" +
                "mType=" + mType +
                ", mKey='" + mKey + '\'' +
                ", mTitle='" + mTitle + '\'' +
                ", mDescription='" + mDescription + '\'' +
                ", mChoiceEntries=" + Arrays.toString(mChoiceEntries) +
                ", mChoiceValues=" + Arrays.toString(mChoiceValues) +
                ", mCurrentValue='" + mCurrentValue + '\'' +
                ", mCurrentValues=" + Arrays.toString(mCurrentValues) +
                ", mRestrictions=" + Arrays.toString(mRestrictions) +
                '}';
    }
}
