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

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.app.Notification;
import android.app.NotificationChannel;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.proto.ProtoOutputStream;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Objects;

/**
 * ZenPolicy determines whether to allow certain notifications and their corresponding sounds to
 * play when a device is in Do Not Disturb mode.
 * ZenPolicy also dictates the visual effects of notifications that are intercepted when
 * a device is in Do Not Disturb mode.
 */
public final class ZenPolicy implements Parcelable {
    private ArrayList<Integer> mPriorityCategories;
    private ArrayList<Integer> mVisualEffects;
    private @PeopleType int mPriorityMessages = PEOPLE_TYPE_UNSET;
    private @PeopleType int mPriorityCalls = PEOPLE_TYPE_UNSET;

    /** @hide */
    @IntDef(prefix = { "PRIORITY_CATEGORY_" }, value = {
            PRIORITY_CATEGORY_REMINDERS,
            PRIORITY_CATEGORY_EVENTS,
            PRIORITY_CATEGORY_MESSAGES,
            PRIORITY_CATEGORY_CALLS,
            PRIORITY_CATEGORY_REPEAT_CALLERS,
            PRIORITY_CATEGORY_ALARMS,
            PRIORITY_CATEGORY_MEDIA,
            PRIORITY_CATEGORY_SYSTEM,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface PriorityCategory {}

    /** @hide */
    public static final int PRIORITY_CATEGORY_REMINDERS = 0;
    /** @hide */
    public static final int PRIORITY_CATEGORY_EVENTS = 1;
    /** @hide */
    public static final int PRIORITY_CATEGORY_MESSAGES = 2;
    /** @hide */
    public static final int PRIORITY_CATEGORY_CALLS = 3;
    /** @hide */
    public static final int PRIORITY_CATEGORY_REPEAT_CALLERS = 4;
    /** @hide */
    public static final int PRIORITY_CATEGORY_ALARMS = 5;
    /** @hide */
    public static final int PRIORITY_CATEGORY_MEDIA = 6;
    /** @hide */
    public static final int PRIORITY_CATEGORY_SYSTEM = 7;

    /** @hide */
    @IntDef(prefix = { "VISUAL_EFFECT_" }, value = {
            VISUAL_EFFECT_FULL_SCREEN_INTENT,
            VISUAL_EFFECT_LIGHTS,
            VISUAL_EFFECT_PEEK,
            VISUAL_EFFECT_STATUS_BAR,
            VISUAL_EFFECT_BADGE,
            VISUAL_EFFECT_AMBIENT,
            VISUAL_EFFECT_NOTIFICATION_LIST,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface VisualEffect {}

    /** @hide */
    public static final int VISUAL_EFFECT_FULL_SCREEN_INTENT = 0;
    /** @hide */
    public static final int VISUAL_EFFECT_LIGHTS = 1;
    /** @hide */
    public static final int VISUAL_EFFECT_PEEK = 2;
    /** @hide */
    public static final int VISUAL_EFFECT_STATUS_BAR = 3;
    /** @hide */
    public static final int VISUAL_EFFECT_BADGE = 4;
    /** @hide */
    public static final int VISUAL_EFFECT_AMBIENT = 5;
    /** @hide */
    public static final int VISUAL_EFFECT_NOTIFICATION_LIST = 6;

    /** @hide */
    @IntDef(prefix = { "PEOPLE_TYPE_" }, value = {
            PEOPLE_TYPE_UNSET,
            PEOPLE_TYPE_ANYONE,
            PEOPLE_TYPE_CONTACTS,
            PEOPLE_TYPE_STARRED,
            PEOPLE_TYPE_NONE,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface PeopleType {}

    /**
     * Used to indicate no preference for the type of people that can bypass dnd for either
     * calls or messages.
     */
    public static final int PEOPLE_TYPE_UNSET = 0;

    /**
     * Used to indicate all calls or messages can bypass dnd.
     */
    public static final int PEOPLE_TYPE_ANYONE = 1;

    /**
     * Used to indicate calls or messages from contacts can bypass dnd.
     */
    public static final int PEOPLE_TYPE_CONTACTS = 2;

    /**
     * Used to indicate calls or messages from starred contacts can bypass dnd.
     */
    public static final int PEOPLE_TYPE_STARRED = 3;

    /**
     * Used to indicate no calls or messages can bypass dnd.
     */
    public static final int PEOPLE_TYPE_NONE = 4;

    /** @hide */
    @IntDef(prefix = { "STATE_" }, value = {
            STATE_UNSET,
            STATE_ALLOW,
            STATE_DISALLOW,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface State {}

    /**
     * Indicates no preference for whether a type of sound or visual effect is or isn't allowed
     * to play/show when DND is active.  Will default to the current set policy.
     */
    public static final int STATE_UNSET = 0;

    /**
     * Indicates a type of sound or visual effect is allowed to play/show when DND is active.
     */
    public static final int STATE_ALLOW = 1;

    /**
     * Indicates a type of sound or visual effect is not allowed to play/show when DND is active.
     */
    public static final int STATE_DISALLOW = 2;

    /** @hide */
    public ZenPolicy() {
        mPriorityCategories = new ArrayList<>(Collections.nCopies(8, 0));
        mVisualEffects = new ArrayList<>(Collections.nCopies(7, 0));
    }

    /**
     * Message senders that can bypass DND.
     * @return {@link #PEOPLE_TYPE_UNSET}, {@link #PEOPLE_TYPE_ANYONE},
     * {@link #PEOPLE_TYPE_CONTACTS}, {@link #PEOPLE_TYPE_STARRED} or {@link #PEOPLE_TYPE_NONE}
     */
    public @PeopleType int getPriorityMessageSenders() {
        return mPriorityMessages;
    }

    /**
     * Callers that can bypass DND.
     * @return {@link #PEOPLE_TYPE_UNSET}, {@link #PEOPLE_TYPE_ANYONE},
     * {@link #PEOPLE_TYPE_CONTACTS}, {@link #PEOPLE_TYPE_STARRED} or {@link #PEOPLE_TYPE_NONE}
     */
    public @PeopleType int getPriorityCallSenders() {
        return mPriorityCalls;
    }

    /**
     * Whether this policy wants to allow notifications with category
     * {@link Notification#CATEGORY_REMINDER} to play sounds and visually appear
     * or to intercept them when DND is active.
     * @return {@link #STATE_UNSET}, {@link #STATE_ALLOW} or {@link #STATE_DISALLOW}
     */
    public @State int getPriorityCategoryReminders() {
        return mPriorityCategories.get(PRIORITY_CATEGORY_REMINDERS);
    }

    /**
     * Whether this policy wants to allow notifications with category
     * {@link Notification#CATEGORY_EVENT} to play sounds and visually appear
     * or to intercept them when DND is active.
     * @return {@link #STATE_UNSET}, {@link #STATE_ALLOW} or {@link #STATE_DISALLOW}
     */
    public @State int getPriorityCategoryEvents() {
        return mPriorityCategories.get(PRIORITY_CATEGORY_EVENTS);
    }

    /**
     * Whether this policy wants to allow notifications with category
     * {@link Notification#CATEGORY_MESSAGE} to play sounds and visually appear
     * or to intercept them when DND is active.  Types of message senders that are allowed
     * are specified by {@link #getPriorityMessageSenders}.
     * @return {@link #STATE_UNSET}, {@link #STATE_ALLOW} or {@link #STATE_DISALLOW}
     */
    public @State int getPriorityCategoryMessages() {
        return mPriorityCategories.get(PRIORITY_CATEGORY_MESSAGES);
    }

    /**
     * Whether this policy wants to allow notifications with category
     * {@link Notification#CATEGORY_CALL} to play sounds and visually appear
     * or to intercept them when DND is active.  Types of callers that are allowed
     * are specified by {@link #getPriorityCallSenders()}.
     * @return {@link #STATE_UNSET}, {@link #STATE_ALLOW} or {@link #STATE_DISALLOW}
     */
    public @State int getPriorityCategoryCalls() {
        return mPriorityCategories.get(PRIORITY_CATEGORY_CALLS);
    }

    /**
     * Whether this policy wants to allow repeat callers (notifications with category
     * {@link Notification#CATEGORY_CALL} that have recently called) to play sounds and
     * visually appear or to intercept them when DND is active.
     * @return {@link #STATE_UNSET}, {@link #STATE_ALLOW} or {@link #STATE_DISALLOW}
     */
    public @State int getPriorityCategoryRepeatCallers() {
        return mPriorityCategories.get(PRIORITY_CATEGORY_REPEAT_CALLERS);
    }

    /**
     * Whether this policy wants to allow notifications with category
     * {@link Notification#CATEGORY_ALARM} to play sounds and visually appear
     * or to intercept them when DND is active.
     * When alarms are {@link #STATE_DISALLOW disallowed}, the alarm stream will be muted when DND
     * is active.
     * @return {@link #STATE_UNSET}, {@link #STATE_ALLOW} or {@link #STATE_DISALLOW}
     */
    public @State int getPriorityCategoryAlarms() {
        return mPriorityCategories.get(PRIORITY_CATEGORY_ALARMS);
    }

    /**
     * Whether this policy wants to allow media notifications to play sounds and visually appear
     * or to intercept them when DND is active.
     * When media is {@link #STATE_DISALLOW disallowed}, the media stream will be muted when DND is
     * active.
     * @return {@link #STATE_UNSET}, {@link #STATE_ALLOW} or {@link #STATE_DISALLOW}
     */
    public @State int getPriorityCategoryMedia() {
        return mPriorityCategories.get(PRIORITY_CATEGORY_MEDIA);
    }

    /**
     * Whether this policy wants to allow system sounds when DND is active.
     * When system is {@link #STATE_DISALLOW}, the system stream will be muted when DND is active.
     * @return {@link #STATE_UNSET}, {@link #STATE_ALLOW} or {@link #STATE_DISALLOW}
     */
    public @State int getPriorityCategorySystem() {
        return mPriorityCategories.get(PRIORITY_CATEGORY_SYSTEM);
    }

    /**
     * Whether this policy allows {@link Notification#fullScreenIntent full screen intents} from
     * notifications intercepted by DND.
     */
    public @State int getVisualEffectFullScreenIntent() {
        return mVisualEffects.get(VISUAL_EFFECT_FULL_SCREEN_INTENT);
    }

    /**
     * Whether this policy allows {@link NotificationChannel#shouldShowLights() notification
     * lights} from notifications intercepted by DND.
     */
    public @State int getVisualEffectLights() {
        return mVisualEffects.get(VISUAL_EFFECT_LIGHTS);
    }

    /**
     * Whether this policy allows peeking from notifications intercepted by DND.
     */
    public @State int getVisualEffectPeek() {
        return mVisualEffects.get(VISUAL_EFFECT_PEEK);
    }

    /**
     * Whether this policy allows notifications intercepted by DND from appearing in the status bar
     * on devices that support status bars.
     */
    public @State int getVisualEffectStatusBar() {
        return mVisualEffects.get(VISUAL_EFFECT_STATUS_BAR);
    }

    /**
     * Whether this policy allows {@link NotificationChannel#canShowBadge() badges} from
     * notifications intercepted by DND on devices that support badging.
     */
    public @State int getVisualEffectBadge() {
        return mVisualEffects.get(VISUAL_EFFECT_BADGE);
    }

    /**
     * Whether this policy allows notifications intercepted by DND from appearing on ambient
     * displays on devices that support ambient display.
     */
    public @State int getVisualEffectAmbient() {
        return mVisualEffects.get(VISUAL_EFFECT_AMBIENT);
    }

    /**
     * Whether this policy allows notifications intercepted by DND from appearing in notification
     * list views like the notification shade or lockscreen on devices that support those
     * views.
     */
    public @State int getVisualEffectNotificationList() {
        return mVisualEffects.get(VISUAL_EFFECT_NOTIFICATION_LIST);
    }

    /**
     * Whether this policy hides all visual effects
     * @hide
     */
    public boolean shouldHideAllVisualEffects() {
        for (int i = 0; i < mVisualEffects.size(); i++) {
            if (mVisualEffects.get(i) != STATE_DISALLOW) {
                return false;
            }
        }
        return true;
    }

    /**
     * Whether this policy shows all visual effects
     * @hide
     */
    public boolean shouldShowAllVisualEffects() {
        for (int i = 0; i < mVisualEffects.size(); i++) {
            if (mVisualEffects.get(i) != STATE_ALLOW) {
                return false;
            }
        }
        return true;
    }

    /**
     * Builder class for {@link ZenPolicy} objects.
     * Provides a convenient way to set the various fields of a {@link ZenPolicy}.  If a field
     * is not set, it is (@link STATE_UNSET} and will not change the current set policy.
     */
    public static final class Builder {
        private ZenPolicy mZenPolicy;

        public Builder() {
            mZenPolicy = new ZenPolicy();
        }

        /**
         * @hide
         */
        public Builder(ZenPolicy policy) {
            if (policy != null) {
                mZenPolicy = policy.copy();
            } else {
                mZenPolicy = new ZenPolicy();
            }
        }

        /**
         * Builds the current ZenPolicy.
         */
        public @NonNull ZenPolicy build() {
            return mZenPolicy.copy();
        }

        /**
         * Allows all notifications to bypass DND and unmutes all streams.
         */
        public @NonNull Builder allowAllSounds() {
            for (int i = 0; i < mZenPolicy.mPriorityCategories.size(); i++) {
                mZenPolicy.mPriorityCategories.set(i, STATE_ALLOW);
            }
            mZenPolicy.mPriorityMessages = PEOPLE_TYPE_ANYONE;
            mZenPolicy.mPriorityCalls = PEOPLE_TYPE_ANYONE;
            return this;
        }

        /**
         * Intercepts all notifications and prevents them from playing sounds
         * when DND is active. Also mutes alarm, system and media streams.
         * Notification channels can still play sounds only if they
         * {@link NotificationChannel#canBypassDnd can bypass DND}. If no channels can bypass DND,
         * the ringer stream is also muted.
         */
        public @NonNull Builder disallowAllSounds() {
            for (int i = 0; i < mZenPolicy.mPriorityCategories.size(); i++) {
                mZenPolicy.mPriorityCategories.set(i, STATE_DISALLOW);
            }
            mZenPolicy.mPriorityMessages = PEOPLE_TYPE_NONE;
            mZenPolicy.mPriorityCalls = PEOPLE_TYPE_NONE;
            return this;
        }

        /**
         * Allows notifications intercepted by DND to show on all surfaces when DND is active.
         */
        public @NonNull Builder showAllVisualEffects() {
            for (int i = 0; i < mZenPolicy.mVisualEffects.size(); i++) {
                mZenPolicy.mVisualEffects.set(i, STATE_ALLOW);
            }
            return this;
        }

        /**
         * Disallows notifications intercepted by DND from showing when DND is active.
         */
        public @NonNull Builder hideAllVisualEffects() {
            for (int i = 0; i < mZenPolicy.mVisualEffects.size(); i++) {
                mZenPolicy.mVisualEffects.set(i, STATE_DISALLOW);
            }
            return this;
        }

        /**
         * Unsets a priority category, neither allowing or disallowing. When applying this policy,
         * unset categories will default to the current applied policy.
         * @hide
         */
        public @NonNull Builder unsetPriorityCategory(@PriorityCategory int category) {
            mZenPolicy.mPriorityCategories.set(category, STATE_UNSET);

            if (category == PRIORITY_CATEGORY_MESSAGES) {
                mZenPolicy.mPriorityMessages = STATE_UNSET;
            } else if (category == PRIORITY_CATEGORY_CALLS) {
                mZenPolicy.mPriorityCalls = STATE_UNSET;
            }

            return this;
        }

        /**
         * Unsets a visual effect, neither allowing or disallowing. When applying this policy,
         * unset effects will default to the current applied policy.
         * @hide
         */
        public @NonNull Builder unsetVisualEffect(@VisualEffect int effect) {
            mZenPolicy.mVisualEffects.set(effect, STATE_UNSET);
            return this;
        }

        /**
         * Whether to allow notifications with category {@link Notification#CATEGORY_REMINDER}
         * to play sounds and visually appear or to intercept them when DND is active.
         */
        public @NonNull Builder allowReminders(boolean allow) {
            mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_REMINDERS,
                    allow ? STATE_ALLOW : STATE_DISALLOW);
            return this;
        }

        /**
         * Whether to allow notifications with category {@link Notification#CATEGORY_EVENT}
         * to play sounds and visually appear or to intercept them when DND is active.
         */
        public @NonNull Builder allowEvents(boolean allow) {
            mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_EVENTS,
                    allow ? STATE_ALLOW : STATE_DISALLOW);
            return this;
        }

        /**
         * Whether to allow notifications with category {@link Notification#CATEGORY_MESSAGE}
         * that match audienceType to play sounds and visually appear or to intercept
         * them when DND is active.
         * @param audienceType message senders that are allowed to bypass DND
         */
        public @NonNull Builder allowMessages(@PeopleType int audienceType) {
            if (audienceType == STATE_UNSET) {
                return unsetPriorityCategory(PRIORITY_CATEGORY_MESSAGES);
            }

            if (audienceType == PEOPLE_TYPE_NONE) {
                mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_MESSAGES, STATE_DISALLOW);
            } else if (audienceType == PEOPLE_TYPE_ANYONE || audienceType == PEOPLE_TYPE_CONTACTS
                    || audienceType == PEOPLE_TYPE_STARRED) {
                mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_MESSAGES, STATE_ALLOW);
            } else {
                return this;
            }

            mZenPolicy.mPriorityMessages = audienceType;
            return this;
        }

        /**
         * Whether to allow notifications with category {@link Notification#CATEGORY_CALL}
         * that match audienceType to play sounds and visually appear or to intercept
         * them when DND is active.
         * @param audienceType callers that are allowed to bypass DND
         */
        public @NonNull  Builder allowCalls(@PeopleType int audienceType) {
            if (audienceType == STATE_UNSET) {
                return unsetPriorityCategory(PRIORITY_CATEGORY_CALLS);
            }

            if (audienceType == PEOPLE_TYPE_NONE) {
                mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_CALLS, STATE_DISALLOW);
            } else if (audienceType == PEOPLE_TYPE_ANYONE || audienceType == PEOPLE_TYPE_CONTACTS
                    || audienceType == PEOPLE_TYPE_STARRED) {
                mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_CALLS, STATE_ALLOW);
            } else {
                return this;
            }

            mZenPolicy.mPriorityCalls = audienceType;
            return this;
        }

        /**
         * Whether to allow repeat callers (notifications with category
         * {@link Notification#CATEGORY_CALL} that have recently called
         * to play sounds and visually appear.
         */
        public @NonNull Builder allowRepeatCallers(boolean allow) {
            mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_REPEAT_CALLERS,
                    allow ? STATE_ALLOW : STATE_DISALLOW);
            return this;
        }


        /**
         * Whether to allow notifications with category {@link Notification#CATEGORY_ALARM}
         * to play sounds and visually appear or to intercept them when DND is active.
         * Disallowing alarms will mute the alarm stream when DND is active.
         */
        public @NonNull Builder allowAlarms(boolean allow) {
            mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_ALARMS,
                    allow ? STATE_ALLOW : STATE_DISALLOW);
            return this;
        }

        /**
         * Whether to allow media notifications to play sounds and visually
         * appear or to intercept them when DND is active.
         * Disallowing media will mute the media stream when DND is active.
         */
        public @NonNull Builder allowMedia(boolean allow) {
            mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_MEDIA,
                    allow ? STATE_ALLOW : STATE_DISALLOW);
            return this;
        }

        /**
         * Whether to allow system sounds to play when DND is active.
         * Disallowing system sounds will mute the system stream when DND is active.
         */
        public @NonNull Builder allowSystem(boolean allow) {
            mZenPolicy.mPriorityCategories.set(PRIORITY_CATEGORY_SYSTEM,
                    allow ? STATE_ALLOW : STATE_DISALLOW);
            return this;
        }

        /**
         * Whether to allow {@link PriorityCategory} sounds to play when DND is active.
         * @hide
         */
        public @NonNull Builder allowCategory(@PriorityCategory int category, boolean allow) {
            switch (category) {
                case PRIORITY_CATEGORY_ALARMS:
                    allowAlarms(allow);
                    break;
                case PRIORITY_CATEGORY_MEDIA:
                    allowMedia(allow);
                    break;
                case PRIORITY_CATEGORY_SYSTEM:
                    allowSystem(allow);
                    break;
                case PRIORITY_CATEGORY_REMINDERS:
                    allowReminders(allow);
                    break;
                case PRIORITY_CATEGORY_EVENTS:
                    allowEvents(allow);
                    break;
                case PRIORITY_CATEGORY_REPEAT_CALLERS:
                    allowRepeatCallers(allow);
                    break;
            }
            return this;
        }

        /**
         * Whether {@link Notification#fullScreenIntent full screen intents} that are intercepted
         * by DND are shown.
         */
        public @NonNull Builder showFullScreenIntent(boolean show) {
            mZenPolicy.mVisualEffects.set(VISUAL_EFFECT_FULL_SCREEN_INTENT,
                    show ? STATE_ALLOW : STATE_DISALLOW);
            return this;
        }

        /**
         * Whether {@link NotificationChannel#shouldShowLights() notification lights} from
         * notifications intercepted by DND are blocked.
         */
        public @NonNull Builder showLights(boolean show) {
            mZenPolicy.mVisualEffects.set(VISUAL_EFFECT_LIGHTS,
                    show ? STATE_ALLOW : STATE_DISALLOW);
            return this;
        }

        /**
         * Whether notifications intercepted by DND are prevented from peeking.
         */
        public @NonNull Builder showPeeking(boolean show) {
            mZenPolicy.mVisualEffects.set(VISUAL_EFFECT_PEEK,
                    show ? STATE_ALLOW : STATE_DISALLOW);
            return this;
        }

        /**
         * Whether notifications intercepted by DND are prevented from appearing in the status bar
         * on devices that support status bars.
         */
        public @NonNull Builder showStatusBarIcons(boolean show) {
            mZenPolicy.mVisualEffects.set(VISUAL_EFFECT_STATUS_BAR,
                    show ? STATE_ALLOW : STATE_DISALLOW);
            return this;
        }

        /**
         * Whether {@link NotificationChannel#canShowBadge() badges} from
         * notifications intercepted by DND are allowed on devices that support badging.
         */
        public @NonNull Builder showBadges(boolean show) {
            mZenPolicy.mVisualEffects.set(VISUAL_EFFECT_BADGE,
                    show ? STATE_ALLOW : STATE_DISALLOW);
            return this;
        }

        /**
         * Whether notification intercepted by DND are prevented from appearing on ambient displays
         * on devices that support ambient display.
         */
        public @NonNull Builder showInAmbientDisplay(boolean show) {
            mZenPolicy.mVisualEffects.set(VISUAL_EFFECT_AMBIENT,
                    show ? STATE_ALLOW : STATE_DISALLOW);
            return this;
        }

        /**
         * Whether notification intercepted by DND are prevented from appearing in notification
         * list views like the notification shade or lockscreen on devices that support those
         * views.
         */
        public @NonNull Builder showInNotificationList(boolean show) {
            mZenPolicy.mVisualEffects.set(VISUAL_EFFECT_NOTIFICATION_LIST,
                    show ? STATE_ALLOW : STATE_DISALLOW);
            return this;
        }

        /**
         * Whether notifications intercepted by DND are prevented from appearing for
         * {@link VisualEffect}
         * @hide
         */
        public @NonNull Builder showVisualEffect(@VisualEffect int effect, boolean show) {
            switch (effect) {
                case VISUAL_EFFECT_FULL_SCREEN_INTENT:
                    showFullScreenIntent(show);
                    break;
                case VISUAL_EFFECT_LIGHTS:
                    showLights(show);
                    break;
                case VISUAL_EFFECT_PEEK:
                    showPeeking(show);
                    break;
                case VISUAL_EFFECT_STATUS_BAR:
                    showStatusBarIcons(show);
                    break;
                case VISUAL_EFFECT_BADGE:
                    showBadges(show);
                    break;
                case VISUAL_EFFECT_AMBIENT:
                    showInAmbientDisplay(show);
                    break;
                case VISUAL_EFFECT_NOTIFICATION_LIST:
                    showInNotificationList(show);
                    break;
            }
            return this;
        }
    }

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeList(mPriorityCategories);
        dest.writeList(mVisualEffects);
        dest.writeInt(mPriorityCalls);
        dest.writeInt(mPriorityMessages);
    }

    public static final @android.annotation.NonNull Parcelable.Creator<ZenPolicy> CREATOR =
            new Parcelable.Creator<ZenPolicy>() {
        @Override
        public ZenPolicy createFromParcel(Parcel source) {
            ZenPolicy policy = new ZenPolicy();
            policy.mPriorityCategories = source.readArrayList(Integer.class.getClassLoader());
            policy.mVisualEffects = source.readArrayList(Integer.class.getClassLoader());
            policy.mPriorityCalls = source.readInt();
            policy.mPriorityMessages = source.readInt();
            return policy;
        }

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

    @Override
    public String toString() {
        return new StringBuilder(ZenPolicy.class.getSimpleName())
                .append('{')
                .append("priorityCategories=[").append(priorityCategoriesToString())
                .append("], visualEffects=[").append(visualEffectsToString())
                .append("], priorityCalls=").append(peopleTypeToString(mPriorityCalls))
                .append(", priorityMessages=").append(peopleTypeToString(mPriorityMessages))
                .append('}')
                .toString();
    }


    private String priorityCategoriesToString() {
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < mPriorityCategories.size(); i++) {
            if (mPriorityCategories.get(i) != STATE_UNSET) {
                builder.append(indexToCategory(i))
                        .append("=")
                        .append(stateToString(mPriorityCategories.get(i)))
                        .append(" ");
            }

        }
        return builder.toString();
    }

    private String visualEffectsToString() {
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < mVisualEffects.size(); i++) {
            if (mVisualEffects.get(i) != STATE_UNSET) {
                builder.append(indexToVisualEffect(i))
                        .append("=")
                        .append(stateToString(mVisualEffects.get(i)))
                        .append(" ");
            }

        }
        return builder.toString();
    }

    private String indexToVisualEffect(@VisualEffect int visualEffectIndex) {
        switch (visualEffectIndex) {
            case VISUAL_EFFECT_FULL_SCREEN_INTENT:
                return "fullScreenIntent";
            case VISUAL_EFFECT_LIGHTS:
                return "lights";
            case VISUAL_EFFECT_PEEK:
                return "peek";
            case VISUAL_EFFECT_STATUS_BAR:
                return "statusBar";
            case VISUAL_EFFECT_BADGE:
                return "badge";
            case VISUAL_EFFECT_AMBIENT:
                return "ambient";
            case VISUAL_EFFECT_NOTIFICATION_LIST:
                return "notificationList";
        }
        return null;
    }

    private String indexToCategory(@PriorityCategory int categoryIndex) {
        switch (categoryIndex) {
            case PRIORITY_CATEGORY_REMINDERS:
                return "reminders";
            case PRIORITY_CATEGORY_EVENTS:
                return "events";
            case PRIORITY_CATEGORY_MESSAGES:
                return "messages";
            case PRIORITY_CATEGORY_CALLS:
                return "calls";
            case PRIORITY_CATEGORY_REPEAT_CALLERS:
                return "repeatCallers";
            case PRIORITY_CATEGORY_ALARMS:
                return "alarms";
            case PRIORITY_CATEGORY_MEDIA:
                return "media";
            case PRIORITY_CATEGORY_SYSTEM:
                return "system";
        }
        return null;
    }

    private String stateToString(@State int state) {
        switch (state) {
            case STATE_UNSET:
                return "unset";
            case STATE_DISALLOW:
                return "disallow";
            case STATE_ALLOW:
                return "allow";
        }
        return "invalidState{" + state + "}";
    }

    private String peopleTypeToString(@PeopleType int peopleType) {
        switch (peopleType) {
            case PEOPLE_TYPE_ANYONE:
                return "anyone";
            case PEOPLE_TYPE_CONTACTS:
                return "contacts";
            case PEOPLE_TYPE_NONE:
                return "none";
            case PEOPLE_TYPE_STARRED:
                return "starred_contacts";
            case STATE_UNSET:
                return "unset";
        }
        return "invalidPeopleType{" + peopleType + "}";
    }

    @Override
    public boolean equals(Object o) {
        if (!(o instanceof ZenPolicy)) return false;
        if (o == this) return true;
        final ZenPolicy other = (ZenPolicy) o;

        return Objects.equals(other.mPriorityCategories, mPriorityCategories)
                && Objects.equals(other.mVisualEffects, mVisualEffects)
                && other.mPriorityCalls == mPriorityCalls
                && other.mPriorityMessages == mPriorityMessages;
    }

    @Override
    public int hashCode() {
        return Objects.hash(mPriorityCategories, mVisualEffects, mPriorityCalls, mPriorityMessages);
    }

    private @ZenPolicy.State int getZenPolicyPriorityCategoryState(@PriorityCategory int
            category) {
        switch (category) {
            case PRIORITY_CATEGORY_REMINDERS:
                return getPriorityCategoryReminders();
            case PRIORITY_CATEGORY_EVENTS:
                return getPriorityCategoryEvents();
            case PRIORITY_CATEGORY_MESSAGES:
                return getPriorityCategoryMessages();
            case PRIORITY_CATEGORY_CALLS:
                return getPriorityCategoryCalls();
            case PRIORITY_CATEGORY_REPEAT_CALLERS:
                return getPriorityCategoryRepeatCallers();
            case PRIORITY_CATEGORY_ALARMS:
                return getPriorityCategoryAlarms();
            case PRIORITY_CATEGORY_MEDIA:
                return getPriorityCategoryMedia();
            case PRIORITY_CATEGORY_SYSTEM:
                return getPriorityCategorySystem();
        }
        return -1;
    }

    private @ZenPolicy.State int getZenPolicyVisualEffectState(@VisualEffect int effect) {
        switch (effect) {
            case VISUAL_EFFECT_FULL_SCREEN_INTENT:
                return getVisualEffectFullScreenIntent();
            case VISUAL_EFFECT_LIGHTS:
                return getVisualEffectLights();
            case VISUAL_EFFECT_PEEK:
                return getVisualEffectPeek();
            case VISUAL_EFFECT_STATUS_BAR:
                return getVisualEffectStatusBar();
            case VISUAL_EFFECT_BADGE:
                return getVisualEffectBadge();
            case VISUAL_EFFECT_AMBIENT:
                return getVisualEffectAmbient();
            case VISUAL_EFFECT_NOTIFICATION_LIST:
                return getVisualEffectNotificationList();
        }
        return -1;
    }

    /** @hide */
    public boolean isCategoryAllowed(@PriorityCategory int category, boolean defaultVal) {
        switch (getZenPolicyPriorityCategoryState(category)) {
            case ZenPolicy.STATE_ALLOW:
                return true;
            case ZenPolicy.STATE_DISALLOW:
                return false;
            default:
                return defaultVal;
        }
    }

    /** @hide */
    public boolean isVisualEffectAllowed(@VisualEffect int effect, boolean defaultVal) {
        switch (getZenPolicyVisualEffectState(effect)) {
            case ZenPolicy.STATE_ALLOW:
                return true;
            case ZenPolicy.STATE_DISALLOW:
                return false;
            default:
                return defaultVal;
        }
    }

    /**
     * Applies another policy on top of this policy
     * @hide
     */
    public void apply(ZenPolicy policyToApply) {
        if (policyToApply == null) {
            return;
        }

        // apply priority categories
        for (int category = 0; category < mPriorityCategories.size(); category++) {
            if (mPriorityCategories.get(category) == STATE_DISALLOW) {
                // if a priority category is already disallowed by the policy, cannot allow
                continue;
            }

            @State int newState = policyToApply.mPriorityCategories.get(category);
            if (newState != STATE_UNSET) {
                mPriorityCategories.set(category, newState);

                if (category == PRIORITY_CATEGORY_MESSAGES
                        && mPriorityMessages < policyToApply.mPriorityMessages) {
                    mPriorityMessages = policyToApply.mPriorityMessages;
                } else if (category == PRIORITY_CATEGORY_CALLS
                        && mPriorityCalls < policyToApply.mPriorityCalls) {
                    mPriorityCalls = policyToApply.mPriorityCalls;
                }
            }
        }

        // apply visual effects
        for (int visualEffect = 0; visualEffect < mVisualEffects.size(); visualEffect++) {
            if (mVisualEffects.get(visualEffect) == STATE_DISALLOW) {
                // if a visual effect is already disallowed by the policy, cannot allow
                continue;
            }

            if (policyToApply.mVisualEffects.get(visualEffect) != STATE_UNSET) {
                mVisualEffects.set(visualEffect, policyToApply.mVisualEffects.get(visualEffect));
            }
        }
    }

    /**
     * @hide
     */
    public void writeToProto(ProtoOutputStream proto, long fieldId) {
        final long token = proto.start(fieldId);

        proto.write(ZenPolicyProto.REMINDERS, getPriorityCategoryReminders());
        proto.write(ZenPolicyProto.EVENTS, getPriorityCategoryEvents());
        proto.write(ZenPolicyProto.MESSAGES, getPriorityCategoryMessages());
        proto.write(ZenPolicyProto.CALLS, getPriorityCategoryCalls());
        proto.write(ZenPolicyProto.REPEAT_CALLERS, getPriorityCategoryRepeatCallers());
        proto.write(ZenPolicyProto.ALARMS, getPriorityCategoryAlarms());
        proto.write(ZenPolicyProto.MEDIA, getPriorityCategoryMedia());
        proto.write(ZenPolicyProto.SYSTEM, getPriorityCategorySystem());

        proto.write(ZenPolicyProto.FULL_SCREEN_INTENT, getVisualEffectFullScreenIntent());
        proto.write(ZenPolicyProto.LIGHTS, getVisualEffectLights());
        proto.write(ZenPolicyProto.PEEK, getVisualEffectPeek());
        proto.write(ZenPolicyProto.STATUS_BAR, getVisualEffectStatusBar());
        proto.write(ZenPolicyProto.BADGE, getVisualEffectBadge());
        proto.write(ZenPolicyProto.AMBIENT, getVisualEffectAmbient());
        proto.write(ZenPolicyProto.NOTIFICATION_LIST, getVisualEffectNotificationList());

        proto.write(ZenPolicyProto.PRIORITY_MESSAGES, getPriorityMessageSenders());
        proto.write(ZenPolicyProto.PRIORITY_CALLS, getPriorityCallSenders());
        proto.end(token);
    }

    /**
     * Makes deep copy of this ZenPolicy.
     * @hide
     */
    public @NonNull ZenPolicy copy() {
        final Parcel parcel = Parcel.obtain();
        try {
            writeToParcel(parcel, 0);
            parcel.setDataPosition(0);
            return CREATOR.createFromParcel(parcel);
        } finally {
            parcel.recycle();
        }
    }
}
