ZenModePanel.java revision 8263c3e0647e0d9622585f1c196ceb8d2fde695e
18600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock/*
28600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock * Copyright (C) 2014 The Android Open Source Project
38600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock *
48600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock * Licensed under the Apache License, Version 2.0 (the "License");
58600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock * you may not use this file except in compliance with the License.
68600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock * You may obtain a copy of the License at
78600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock *
88600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock *      http://www.apache.org/licenses/LICENSE-2.0
98600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock *
108600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock * Unless required by applicable law or agreed to in writing, software
118600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock * distributed under the License is distributed on an "AS IS" BASIS,
128600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock * See the License for the specific language governing permissions and
148600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock * limitations under the License.
158600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock */
168600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock
178600534df66c2ff5846ed230b50c56229322d48aJohn Spurlockpackage com.android.systemui.volume;
188600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock
19ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlockimport android.animation.Animator;
20ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlockimport android.animation.AnimatorListenerAdapter;
218600534df66c2ff5846ed230b50c56229322d48aJohn Spurlockimport android.content.Context;
228600534df66c2ff5846ed230b50c56229322d48aJohn Spurlockimport android.content.Intent;
23856edebad73560e9b1cce021a7de9a0470d07176John Spurlockimport android.content.SharedPreferences;
24856edebad73560e9b1cce021a7de9a0470d07176John Spurlockimport android.content.SharedPreferences.OnSharedPreferenceChangeListener;
258600534df66c2ff5846ed230b50c56229322d48aJohn Spurlockimport android.net.Uri;
268600534df66c2ff5846ed230b50c56229322d48aJohn Spurlockimport android.os.Handler;
278600534df66c2ff5846ed230b50c56229322d48aJohn Spurlockimport android.os.Looper;
288600534df66c2ff5846ed230b50c56229322d48aJohn Spurlockimport android.os.Message;
298600534df66c2ff5846ed230b50c56229322d48aJohn Spurlockimport android.provider.Settings;
30ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlockimport android.provider.Settings.Global;
318600534df66c2ff5846ed230b50c56229322d48aJohn Spurlockimport android.service.notification.Condition;
32856edebad73560e9b1cce021a7de9a0470d07176John Spurlockimport android.service.notification.ZenModeConfig;
338600534df66c2ff5846ed230b50c56229322d48aJohn Spurlockimport android.util.AttributeSet;
34856edebad73560e9b1cce021a7de9a0470d07176John Spurlockimport android.util.Log;
358600534df66c2ff5846ed230b50c56229322d48aJohn Spurlockimport android.view.ContextThemeWrapper;
368600534df66c2ff5846ed230b50c56229322d48aJohn Spurlockimport android.view.LayoutInflater;
378600534df66c2ff5846ed230b50c56229322d48aJohn Spurlockimport android.view.View;
38ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlockimport android.view.animation.AnimationUtils;
39ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlockimport android.view.animation.Interpolator;
408600534df66c2ff5846ed230b50c56229322d48aJohn Spurlockimport android.widget.CompoundButton;
418600534df66c2ff5846ed230b50c56229322d48aJohn Spurlockimport android.widget.CompoundButton.OnCheckedChangeListener;
428600534df66c2ff5846ed230b50c56229322d48aJohn Spurlockimport android.widget.ImageView;
438600534df66c2ff5846ed230b50c56229322d48aJohn Spurlockimport android.widget.LinearLayout;
448600534df66c2ff5846ed230b50c56229322d48aJohn Spurlockimport android.widget.RadioButton;
458600534df66c2ff5846ed230b50c56229322d48aJohn Spurlockimport android.widget.TextView;
468600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock
478600534df66c2ff5846ed230b50c56229322d48aJohn Spurlockimport com.android.systemui.R;
488600534df66c2ff5846ed230b50c56229322d48aJohn Spurlockimport com.android.systemui.statusbar.policy.ZenModeController;
498600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock
508600534df66c2ff5846ed230b50c56229322d48aJohn Spurlockimport java.util.Arrays;
51856edebad73560e9b1cce021a7de9a0470d07176John Spurlockimport java.util.Objects;
528600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock
538600534df66c2ff5846ed230b50c56229322d48aJohn Spurlockpublic class ZenModePanel extends LinearLayout {
54ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock    private static final String TAG = "ZenModePanel";
55ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
56856edebad73560e9b1cce021a7de9a0470d07176John Spurlock
57ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock    private static final int[] MINUTE_BUCKETS = DEBUG
58ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock            ? new int[] { 1, 2, 5, 15, 30, 45, 60, 120, 180, 240, 480 }
59ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock            : new int[] { 15, 30, 45, 60, 120, 180, 240, 480 };
60856edebad73560e9b1cce021a7de9a0470d07176John Spurlock    private static final int MIN_BUCKET_MINUTES = MINUTE_BUCKETS[0];
61856edebad73560e9b1cce021a7de9a0470d07176John Spurlock    private static final int MAX_BUCKET_MINUTES = MINUTE_BUCKETS[MINUTE_BUCKETS.length - 1];
62856edebad73560e9b1cce021a7de9a0470d07176John Spurlock    private static final int DEFAULT_BUCKET_INDEX = Arrays.binarySearch(MINUTE_BUCKETS, 60);
63ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock    private static final int FOREVER_CONDITION_INDEX = 0;
64ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock    private static final int TIME_CONDITION_INDEX = 1;
65ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock    private static final int FIRST_CONDITION_INDEX = 2;
66ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock    private static final float SILENT_HINT_PULSE_SCALE = 1.1f;
67856edebad73560e9b1cce021a7de9a0470d07176John Spurlock
68856edebad73560e9b1cce021a7de9a0470d07176John Spurlock    private static final int SECONDS_MS = 1000;
69856edebad73560e9b1cce021a7de9a0470d07176John Spurlock    private static final int MINUTES_MS = 60 * SECONDS_MS;
70856edebad73560e9b1cce021a7de9a0470d07176John Spurlock
718600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock    public static final Intent ZEN_SETTINGS = new Intent(Settings.ACTION_ZEN_MODE_SETTINGS);
728600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock
737f1df5e98578f8532a5e009009e7c1f82ed5885cJohn Spurlock    private final Context mContext;
748600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock    private final LayoutInflater mInflater;
758600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock    private final H mHandler = new H();
76856edebad73560e9b1cce021a7de9a0470d07176John Spurlock    private final Favorites mFavorites;
77ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock    private final Interpolator mFastOutSlowInInterpolator;
78856edebad73560e9b1cce021a7de9a0470d07176John Spurlock
79856edebad73560e9b1cce021a7de9a0470d07176John Spurlock    private char mLogTag = '?';
80856edebad73560e9b1cce021a7de9a0470d07176John Spurlock    private String mTag;
81ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock
82ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock    private SegmentedButtons mZenButtons;
83ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock    private View mZenSubhead;
84ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock    private TextView mZenSubheadCollapsed;
85ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock    private TextView mZenSubheadExpanded;
867f8f22a53005f776c8ee4d299e748e74b077ffd9John Spurlock    private View mMoreSettings;
87ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock    private LinearLayout mZenConditions;
88ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock
898600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock    private Callback mCallback;
908600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock    private ZenModeController mController;
918600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock    private boolean mRequestingConditions;
92856edebad73560e9b1cce021a7de9a0470d07176John Spurlock    private Uri mExitConditionId;
93856edebad73560e9b1cce021a7de9a0470d07176John Spurlock    private int mBucketIndex = -1;
94ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock    private boolean mExpanded;
95ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock    private int mAttachedZen;
96ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock    private String mExitConditionText;
978600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock
988600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock    public ZenModePanel(Context context, AttributeSet attrs) {
998600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        super(context, attrs);
1007f1df5e98578f8532a5e009009e7c1f82ed5885cJohn Spurlock        mContext = context;
101856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        mFavorites = new Favorites();
102f7d22132c2c9b83134b05aaed63a89f61c639fd9John Spurlock        mInflater = LayoutInflater.from(mContext.getApplicationContext());
103ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(mContext,
104ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock                android.R.interpolator.fast_out_slow_in);
105856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        updateTag();
106856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        if (DEBUG) Log.d(mTag, "new ZenModePanel");
107856edebad73560e9b1cce021a7de9a0470d07176John Spurlock    }
108856edebad73560e9b1cce021a7de9a0470d07176John Spurlock
109856edebad73560e9b1cce021a7de9a0470d07176John Spurlock    private void updateTag() {
110ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        mTag = TAG + "/" + mLogTag + "/" + Integer.toHexString(System.identityHashCode(this));
1118600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock    }
1128600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock
1138600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock    @Override
1148600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock    protected void onFinishInflate() {
1158600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        super.onFinishInflate();
116ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock
117ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        mZenButtons = (SegmentedButtons) findViewById(R.id.zen_buttons);
118ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        mZenButtons.addButton(R.string.interruption_level_none, Global.ZEN_MODE_NO_INTERRUPTIONS);
119ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        mZenButtons.addButton(R.string.interruption_level_priority,
120ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock                Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
121ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        mZenButtons.addButton(R.string.interruption_level_all, Global.ZEN_MODE_OFF);
122ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        mZenButtons.setCallback(mZenButtonsCallback);
123ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock
124ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        mZenSubhead = findViewById(R.id.zen_subhead);
125ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock
126ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        mZenSubheadCollapsed = (TextView) findViewById(R.id.zen_subhead_collapsed);
127ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        mZenSubheadCollapsed.setOnClickListener(new View.OnClickListener() {
128ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock            @Override
129ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock            public void onClick(View v) {
130ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock                setExpanded(true);
131ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock                fireInteraction();
132ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock            }
133ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        });
134ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock
135ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        mZenSubheadExpanded = (TextView) findViewById(R.id.zen_subhead_expanded);
136ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock
137ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        mMoreSettings = findViewById(R.id.zen_more_settings);
1387f8f22a53005f776c8ee4d299e748e74b077ffd9John Spurlock        mMoreSettings.setOnClickListener(new View.OnClickListener() {
1398600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock            @Override
1408600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock            public void onClick(View v) {
1418600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock                fireMoreSettings();
142ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock                fireInteraction();
1438600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock            }
1448600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        });
145ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock
146ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        mZenConditions = (LinearLayout) findViewById(R.id.zen_conditions);
1478600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock    }
1488600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock
1498600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock    @Override
150856edebad73560e9b1cce021a7de9a0470d07176John Spurlock    protected void onAttachedToWindow() {
151856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        super.onAttachedToWindow();
152856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        if (DEBUG) Log.d(mTag, "onAttachedToWindow");
153ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        mAttachedZen = getSelectedZen(-1);
154ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        refreshExitConditionText();
155856edebad73560e9b1cce021a7de9a0470d07176John Spurlock    }
156856edebad73560e9b1cce021a7de9a0470d07176John Spurlock
157856edebad73560e9b1cce021a7de9a0470d07176John Spurlock    @Override
158856edebad73560e9b1cce021a7de9a0470d07176John Spurlock    protected void onDetachedFromWindow() {
159856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        super.onDetachedFromWindow();
160856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        if (DEBUG) Log.d(mTag, "onDetachedFromWindow");
161ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        mAttachedZen = -1;
162ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        setExpanded(false);
163856edebad73560e9b1cce021a7de9a0470d07176John Spurlock    }
164856edebad73560e9b1cce021a7de9a0470d07176John Spurlock
165ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock    private void setExpanded(boolean expanded) {
166ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        if (expanded == mExpanded) return;
167ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        mExpanded = expanded;
168ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        updateWidgets();
169ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        setRequestingConditions(mExpanded);
170ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        fireExpanded();
1718600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock    }
1728600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock
1738600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock    /** Start or stop requesting relevant zen mode exit conditions */
1748600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock    private void setRequestingConditions(boolean requesting) {
1758600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        if (mRequestingConditions == requesting) return;
176856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        if (DEBUG) Log.d(mTag, "setRequestingConditions " + requesting);
1778600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        mRequestingConditions = requesting;
178856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        if (mController != null) {
179856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            mController.requestConditions(mRequestingConditions);
180856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        }
1818600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        if (mRequestingConditions) {
182856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            Condition timeCondition = parseExistingTimeCondition(mExitConditionId);
183856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            if (timeCondition != null) {
184856edebad73560e9b1cce021a7de9a0470d07176John Spurlock                mBucketIndex = -1;
185856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            } else {
186856edebad73560e9b1cce021a7de9a0470d07176John Spurlock                mBucketIndex = DEFAULT_BUCKET_INDEX;
187856edebad73560e9b1cce021a7de9a0470d07176John Spurlock                timeCondition = newTimeCondition(MINUTE_BUCKETS[mBucketIndex]);
188856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            }
189856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            if (DEBUG) Log.d(mTag, "Initial bucket index: " + mBucketIndex);
190ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock            handleUpdateConditions(new Condition[0]);  // ensures forever exists
191ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock            bind(timeCondition, mZenConditions.getChildAt(TIME_CONDITION_INDEX));
192ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock            checkForDefault();
1938600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        } else {
194ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock            mZenConditions.removeAllViews();
1958600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        }
1968600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock    }
1978600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock
198ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock    public void init(ZenModeController controller, char logTag) {
1998600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        mController = controller;
200856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        mLogTag = logTag;
201856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        updateTag();
202ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        setExitConditionId(mController.getExitConditionId());
203ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        refreshExitConditionText();
204ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        mAttachedZen = getSelectedZen(-1);
205ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        handleUpdateZen(mController.getZen());
206856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        if (DEBUG) Log.d(mTag, "init mExitConditionId=" + mExitConditionId);
207ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        mZenConditions.removeAllViews();
208856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        mController.addCallback(mZenCallback);
209ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock    }
210ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock
211ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock    private void setExitConditionId(Uri exitConditionId) {
212ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        if (Objects.equals(mExitConditionId, exitConditionId)) return;
213ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        mExitConditionId = exitConditionId;
214ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        refreshExitConditionText();
215ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock    }
216ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock
217ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock    private void refreshExitConditionText() {
218ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        if (mExitConditionId == null) {
219ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock            mExitConditionText = mContext.getString(R.string.zen_mode_forever);
220ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        } else if (ZenModeConfig.isValidCountdownConditionId(mExitConditionId)) {
221ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock            mExitConditionText = parseExistingTimeCondition(mExitConditionId).summary;
222ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        } else {
223ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock            mExitConditionText = "(until condition ends)";  // TODO persist current description
224856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        }
2258600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock    }
2268600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock
2278600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock    public void setCallback(Callback callback) {
2288600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        mCallback = callback;
2298600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock    }
2308600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock
231ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock    public void showSilentHint() {
232ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        if (DEBUG) Log.d(mTag, "showSilentHint");
233ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        if (mZenButtons == null || mZenButtons.getChildCount() == 0) return;
234ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        final View noneButton = mZenButtons.getChildAt(0);
235ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        if (noneButton.getScaleX() != 1) return;  // already running
236ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        noneButton.animate().cancel();
237ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        noneButton.animate().scaleX(SILENT_HINT_PULSE_SCALE).scaleY(SILENT_HINT_PULSE_SCALE)
238ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock                .setInterpolator(mFastOutSlowInInterpolator)
239ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock                .setListener(new AnimatorListenerAdapter() {
240ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock                    @Override
241ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock                    public void onAnimationEnd(Animator animation) {
242ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock                        noneButton.animate().scaleX(1).scaleY(1).setListener(null);
243ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock                    }
244ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock                });
245ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock    }
246ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock
247ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock    private void handleUpdateZen(int zen) {
248ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        if (mAttachedZen != -1 && mAttachedZen != zen) {
249ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock            setExpanded(zen != Global.ZEN_MODE_OFF);
250ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock            mAttachedZen = zen;
251ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        }
252ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        mZenButtons.setSelectedValue(zen);
253ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        updateWidgets();
254ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock    }
255ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock
256ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock    private int getSelectedZen(int defValue) {
257ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        final Object zen = mZenButtons.getSelectedValue();
258ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        return zen != null ? (Integer) zen : defValue;
259ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock    }
260ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock
261ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock    private void updateWidgets() {
262ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        final int zen = getSelectedZen(Global.ZEN_MODE_OFF);
263ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        final boolean zenOff = zen == Global.ZEN_MODE_OFF;
264ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        final boolean zenImportant = zen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
265ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        final boolean zenNone = zen == Global.ZEN_MODE_NO_INTERRUPTIONS;
2668263c3e0647e0d9622585f1c196ceb8d2fde695eJohn Spurlock        final boolean foreverSelected = mExitConditionId == null;
267ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock
2688263c3e0647e0d9622585f1c196ceb8d2fde695eJohn Spurlock        mZenSubhead.setVisibility(!zenOff && (mExpanded || !foreverSelected) ? VISIBLE : GONE);
269ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        mZenSubheadExpanded.setVisibility(mExpanded ? VISIBLE : GONE);
270ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        mZenSubheadCollapsed.setVisibility(!mExpanded ? VISIBLE : GONE);
271ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        mMoreSettings.setVisibility(zenImportant && mExpanded ? VISIBLE : GONE);
272ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        mZenConditions.setVisibility(!zenOff && mExpanded ? VISIBLE : GONE);
273ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock
274ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        if (zenNone) {
27586d04fdaa1853cf7ff8ec9aba1dd925dd098167eJohn Spurlock            mZenSubheadExpanded.setText(R.string.zen_no_interruptions_with_warning);
276ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock            mZenSubheadCollapsed.setText(mExitConditionText);
277ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        } else if (zenImportant) {
278ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock            mZenSubheadExpanded.setText(R.string.zen_important_interruptions);
279ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock            mZenSubheadCollapsed.setText(mExitConditionText);
280ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        }
281ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock    }
282ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock
283856edebad73560e9b1cce021a7de9a0470d07176John Spurlock    private Condition parseExistingTimeCondition(Uri conditionId) {
284856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        final long time = ZenModeConfig.tryParseCountdownConditionId(conditionId);
285856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        if (time == 0) return null;
286856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        final long span = time - System.currentTimeMillis();
287856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        if (span <= 0 || span > MAX_BUCKET_MINUTES * MINUTES_MS) return null;
288856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        return timeCondition(time, Math.round(span / (float)MINUTES_MS));
289856edebad73560e9b1cce021a7de9a0470d07176John Spurlock    }
290856edebad73560e9b1cce021a7de9a0470d07176John Spurlock
291856edebad73560e9b1cce021a7de9a0470d07176John Spurlock    private Condition newTimeCondition(int minutesFromNow) {
292856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        final long now = System.currentTimeMillis();
293856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        return timeCondition(now + minutesFromNow * MINUTES_MS, minutesFromNow);
294856edebad73560e9b1cce021a7de9a0470d07176John Spurlock    }
295856edebad73560e9b1cce021a7de9a0470d07176John Spurlock
296856edebad73560e9b1cce021a7de9a0470d07176John Spurlock    private Condition timeCondition(long time, int minutes) {
297856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        final int num = minutes < 60 ? minutes : Math.round(minutes / 60f);
2988600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        final int resId = minutes < 60
2998600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock                ? R.plurals.zen_mode_duration_minutes
3008600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock                : R.plurals.zen_mode_duration_hours;
3018600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        final String caption = mContext.getResources().getQuantityString(resId, num, num);
302856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        final Uri id = ZenModeConfig.toCountdownConditionId(time);
3038600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        return new Condition(id, caption, "", "", 0, Condition.STATE_TRUE,
3048600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock                Condition.FLAG_RELEVANT_NOW);
3058600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock    }
3068600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock
3078600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock    private void handleUpdateConditions(Condition[] conditions) {
3088600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        final int newCount = conditions == null ? 0 : conditions.length;
309ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        if (DEBUG) Log.d(mTag, "handleUpdateConditions newCount=" + newCount);
310ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        for (int i = mZenConditions.getChildCount(); i >= newCount + FIRST_CONDITION_INDEX; i--) {
311ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock            mZenConditions.removeViewAt(i);
3128600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        }
313ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        bind(null, mZenConditions.getChildAt(FOREVER_CONDITION_INDEX));
3148600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        for (int i = 0; i < newCount; i++) {
315ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock            bind(conditions[i], mZenConditions.getChildAt(FIRST_CONDITION_INDEX + i));
3168600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        }
317856edebad73560e9b1cce021a7de9a0470d07176John Spurlock    }
318856edebad73560e9b1cce021a7de9a0470d07176John Spurlock
319856edebad73560e9b1cce021a7de9a0470d07176John Spurlock    private ConditionTag getConditionTagAt(int index) {
320ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        return (ConditionTag) mZenConditions.getChildAt(index).getTag();
321856edebad73560e9b1cce021a7de9a0470d07176John Spurlock    }
322856edebad73560e9b1cce021a7de9a0470d07176John Spurlock
323856edebad73560e9b1cce021a7de9a0470d07176John Spurlock    private void checkForDefault() {
324856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        // are we left without anything selected?  if so, set a default
325ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        for (int i = 0; i < mZenConditions.getChildCount(); i++) {
326856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            if (getConditionTagAt(i).rb.isChecked()) {
327856edebad73560e9b1cce021a7de9a0470d07176John Spurlock                return;
328856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            }
329856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        }
330856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        if (DEBUG) Log.d(mTag, "Selecting a default");
331856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        final int favoriteIndex = mFavorites.getMinuteIndex();
332856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        if (favoriteIndex == -1) {
333ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock            getConditionTagAt(FOREVER_CONDITION_INDEX).rb.setChecked(true);
334856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        } else {
335856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            final Condition c = newTimeCondition(MINUTE_BUCKETS[favoriteIndex]);
336856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            mBucketIndex = favoriteIndex;
337ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock            bind(c, mZenConditions.getChildAt(TIME_CONDITION_INDEX));
338ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock            getConditionTagAt(TIME_CONDITION_INDEX).rb.setChecked(true);
339856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        }
3408600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock    }
3418600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock
342856edebad73560e9b1cce021a7de9a0470d07176John Spurlock    private void handleExitConditionChanged(Uri exitCondition) {
343ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        setExitConditionId(exitCondition);
344856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        if (DEBUG) Log.d(mTag, "handleExitConditionChanged " + mExitConditionId);
345ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        final int N = mZenConditions.getChildCount();
346856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        for (int i = 0; i < N; i++) {
347856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            final ConditionTag tag = getConditionTagAt(i);
348856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            tag.rb.setChecked(Objects.equals(tag.conditionId, exitCondition));
349856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        }
3508600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock    }
3518600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock
3528600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock    private void bind(final Condition condition, View convertView) {
3538600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        final boolean enabled = condition == null || condition.state == Condition.STATE_TRUE;
3548600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        final View row;
3558600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        if (convertView == null) {
3568600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock            row = mInflater.inflate(R.layout.zen_mode_condition, this, false);
357856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            if (DEBUG) Log.d(mTag, "Adding new condition view for: " + condition);
358ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock            mZenConditions.addView(row);
3598600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        } else {
3608600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock            row = convertView;
3618600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        }
362856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        final ConditionTag tag =
363856edebad73560e9b1cce021a7de9a0470d07176John Spurlock                row.getTag() != null ? (ConditionTag) row.getTag() : new ConditionTag();
364856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        row.setTag(tag);
365856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        if (tag.rb == null) {
366856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            tag.rb = (RadioButton) row.findViewById(android.R.id.checkbox);
367856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        }
368856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        tag.conditionId = condition != null ? condition.id : null;
369856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        tag.rb.setEnabled(enabled);
370856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        tag.rb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
3718600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock            @Override
3728600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
373ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock                if (mExpanded && isChecked) {
374856edebad73560e9b1cce021a7de9a0470d07176John Spurlock                    if (DEBUG) Log.d(mTag, "onCheckedChanged " + tag.conditionId);
375ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock                    final int N = mZenConditions.getChildCount();
376856edebad73560e9b1cce021a7de9a0470d07176John Spurlock                    for (int i = 0; i < N; i++) {
377856edebad73560e9b1cce021a7de9a0470d07176John Spurlock                        ConditionTag childTag = getConditionTagAt(i);
378856edebad73560e9b1cce021a7de9a0470d07176John Spurlock                        if (childTag == tag) continue;
379856edebad73560e9b1cce021a7de9a0470d07176John Spurlock                        childTag.rb.setChecked(false);
3808600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock                    }
381856edebad73560e9b1cce021a7de9a0470d07176John Spurlock                    select(tag.conditionId);
3828600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock                    fireInteraction();
3838600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock                }
3848600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock            }
3858600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        });
3868600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        final TextView title = (TextView) row.findViewById(android.R.id.title);
3878600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        if (condition == null) {
3888600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock            title.setText(R.string.zen_mode_forever);
3898600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        } else {
3908600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock            title.setText(condition.summary);
3918600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        }
3928600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        title.setEnabled(enabled);
393ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        title.setAlpha(enabled ? 1 : .4f);
3948600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        final ImageView button1 = (ImageView) row.findViewById(android.R.id.button1);
3958600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        button1.setOnClickListener(new OnClickListener() {
3968600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock            @Override
3978600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock            public void onClick(View v) {
398856edebad73560e9b1cce021a7de9a0470d07176John Spurlock                onClickTimeButton(row, tag, false /*down*/);
3998600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock            }
4008600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        });
4018600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock
4028600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        final ImageView button2 = (ImageView) row.findViewById(android.R.id.button2);
4038600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        button2.setOnClickListener(new OnClickListener() {
4048600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock            @Override
4058600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock            public void onClick(View v) {
406856edebad73560e9b1cce021a7de9a0470d07176John Spurlock                onClickTimeButton(row, tag, true /*up*/);
4078600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock            }
4088600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        });
4098600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        title.setOnClickListener(new OnClickListener() {
4108600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock            @Override
4118600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock            public void onClick(View v) {
412856edebad73560e9b1cce021a7de9a0470d07176John Spurlock                tag.rb.setChecked(true);
4138600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock                fireInteraction();
4148600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock            }
4158600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        });
416856edebad73560e9b1cce021a7de9a0470d07176John Spurlock
417856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        final long time = ZenModeConfig.tryParseCountdownConditionId(tag.conditionId);
418856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        if (time > 0) {
419856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            if (mBucketIndex > -1) {
420856edebad73560e9b1cce021a7de9a0470d07176John Spurlock                button1.setEnabled(mBucketIndex > 0);
421856edebad73560e9b1cce021a7de9a0470d07176John Spurlock                button2.setEnabled(mBucketIndex < MINUTE_BUCKETS.length - 1);
422856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            } else {
423856edebad73560e9b1cce021a7de9a0470d07176John Spurlock                final long span = time - System.currentTimeMillis();
424856edebad73560e9b1cce021a7de9a0470d07176John Spurlock                button1.setEnabled(span > MIN_BUCKET_MINUTES * MINUTES_MS);
425856edebad73560e9b1cce021a7de9a0470d07176John Spurlock                final Condition maxCondition = newTimeCondition(MAX_BUCKET_MINUTES);
426856edebad73560e9b1cce021a7de9a0470d07176John Spurlock                button2.setEnabled(!Objects.equals(condition.summary, maxCondition.summary));
427856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            }
428856edebad73560e9b1cce021a7de9a0470d07176John Spurlock
429856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            button1.setAlpha(button1.isEnabled() ? 1f : .5f);
430856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            button2.setAlpha(button2.isEnabled() ? 1f : .5f);
4318600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        } else {
4328600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock            button1.setVisibility(View.GONE);
4338600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock            button2.setVisibility(View.GONE);
4348600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        }
435856edebad73560e9b1cce021a7de9a0470d07176John Spurlock    }
436856edebad73560e9b1cce021a7de9a0470d07176John Spurlock
437856edebad73560e9b1cce021a7de9a0470d07176John Spurlock    private void onClickTimeButton(View row, ConditionTag tag, boolean up) {
438856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        Condition newCondition = null;
439856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        final int N = MINUTE_BUCKETS.length;
440856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        if (mBucketIndex == -1) {
441856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            // not on a known index, search for the next or prev bucket by time
442856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            final long time = ZenModeConfig.tryParseCountdownConditionId(tag.conditionId);
443856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            final long now = System.currentTimeMillis();
444856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            for (int i = 0; i < N; i++) {
445856edebad73560e9b1cce021a7de9a0470d07176John Spurlock                int j = up ? i : N - 1 - i;
446856edebad73560e9b1cce021a7de9a0470d07176John Spurlock                final int bucketMinutes = MINUTE_BUCKETS[j];
447856edebad73560e9b1cce021a7de9a0470d07176John Spurlock                final long bucketTime = now + bucketMinutes * MINUTES_MS;
448856edebad73560e9b1cce021a7de9a0470d07176John Spurlock                if (up && bucketTime > time || !up && bucketTime < time) {
449856edebad73560e9b1cce021a7de9a0470d07176John Spurlock                    mBucketIndex = j;
450856edebad73560e9b1cce021a7de9a0470d07176John Spurlock                    newCondition = timeCondition(bucketTime, bucketMinutes);
451856edebad73560e9b1cce021a7de9a0470d07176John Spurlock                    break;
452856edebad73560e9b1cce021a7de9a0470d07176John Spurlock                }
453856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            }
454856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            if (newCondition == null) {
455856edebad73560e9b1cce021a7de9a0470d07176John Spurlock                mBucketIndex = DEFAULT_BUCKET_INDEX;
456856edebad73560e9b1cce021a7de9a0470d07176John Spurlock                newCondition = newTimeCondition(MINUTE_BUCKETS[mBucketIndex]);
457856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            }
458856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        } else {
459856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            // on a known index, simply increment or decrement
460856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            mBucketIndex = Math.max(0, Math.min(N - 1, mBucketIndex + (up ? 1 : -1)));
461856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            newCondition = newTimeCondition(MINUTE_BUCKETS[mBucketIndex]);
462856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        }
463856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        bind(newCondition, row);
464856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        tag.rb.setChecked(true);
465856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        select(newCondition.id);
466856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        fireInteraction();
467856edebad73560e9b1cce021a7de9a0470d07176John Spurlock    }
468856edebad73560e9b1cce021a7de9a0470d07176John Spurlock
469856edebad73560e9b1cce021a7de9a0470d07176John Spurlock    private void select(Uri conditionId) {
470856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        if (DEBUG) Log.d(mTag, "select " + conditionId);
471856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        if (mController != null) {
472856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            mController.setExitConditionId(conditionId);
473856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        }
474ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        setExitConditionId(conditionId);
475856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        if (conditionId == null) {
476856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            mFavorites.setMinuteIndex(-1);
477856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        } else if (ZenModeConfig.isValidCountdownConditionId(conditionId) && mBucketIndex != -1) {
478856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            mFavorites.setMinuteIndex(mBucketIndex);
4798600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        }
4808600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock    }
4818600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock
4828600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock    private void fireMoreSettings() {
4838600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        if (mCallback != null) {
4848600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock            mCallback.onMoreSettings();
4858600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        }
4868600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock    }
4878600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock
4888600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock    private void fireInteraction() {
4898600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        if (mCallback != null) {
4908600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock            mCallback.onInteraction();
4918600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        }
4928600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock    }
4938600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock
494ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock    private void fireExpanded() {
495ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        if (mCallback != null) {
496ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock            mCallback.onExpanded(mExpanded);
497ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        }
498ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock    }
499ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock
5008600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock    private final ZenModeController.Callback mZenCallback = new ZenModeController.Callback() {
5018600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        @Override
502ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        public void onZenChanged(int zen) {
503ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock            mHandler.obtainMessage(H.UPDATE_ZEN, zen, 0).sendToTarget();
504ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        }
505ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        @Override
5068600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        public void onConditionsChanged(Condition[] conditions) {
5078600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock            mHandler.obtainMessage(H.UPDATE_CONDITIONS, conditions).sendToTarget();
5088600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        }
509856edebad73560e9b1cce021a7de9a0470d07176John Spurlock
510856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        @Override
511856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        public void onExitConditionChanged(Uri exitConditionId) {
512856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            mHandler.obtainMessage(H.EXIT_CONDITION_CHANGED, exitConditionId).sendToTarget();
513856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        }
5148600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock    };
5158600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock
5168600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock    private final class H extends Handler {
5178600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        private static final int UPDATE_CONDITIONS = 1;
518856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        private static final int EXIT_CONDITION_CHANGED = 2;
519ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        private static final int UPDATE_ZEN = 3;
5208600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock
5218600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        private H() {
5228600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock            super(Looper.getMainLooper());
5238600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        }
5248600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock
5258600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        @Override
5268600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        public void handleMessage(Message msg) {
5278600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock            if (msg.what == UPDATE_CONDITIONS) {
5288600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock                handleUpdateConditions((Condition[])msg.obj);
529ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock                checkForDefault();
530856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            } else if (msg.what == EXIT_CONDITION_CHANGED) {
531856edebad73560e9b1cce021a7de9a0470d07176John Spurlock                handleExitConditionChanged((Uri)msg.obj);
532ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock            } else if (msg.what == UPDATE_ZEN) {
533ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock                handleUpdateZen(msg.arg1);
5348600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock            }
5358600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        }
5368600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock    }
5378600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock
5388600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock    public interface Callback {
5398600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        void onMoreSettings();
5408600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock        void onInteraction();
541ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        void onExpanded(boolean expanded);
5428600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock    }
543856edebad73560e9b1cce021a7de9a0470d07176John Spurlock
544856edebad73560e9b1cce021a7de9a0470d07176John Spurlock    // used as the view tag on condition rows
545856edebad73560e9b1cce021a7de9a0470d07176John Spurlock    private static class ConditionTag {
546856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        RadioButton rb;
547856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        Uri conditionId;
548856edebad73560e9b1cce021a7de9a0470d07176John Spurlock    }
549856edebad73560e9b1cce021a7de9a0470d07176John Spurlock
550856edebad73560e9b1cce021a7de9a0470d07176John Spurlock    private final class Favorites implements OnSharedPreferenceChangeListener {
551856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        private static final String KEY_MINUTE_INDEX = "minuteIndex";
552856edebad73560e9b1cce021a7de9a0470d07176John Spurlock
553856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        private int mMinuteIndex;
554856edebad73560e9b1cce021a7de9a0470d07176John Spurlock
555856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        private Favorites() {
556856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            prefs().registerOnSharedPreferenceChangeListener(this);
557856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            updateMinuteIndex();
558856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        }
559856edebad73560e9b1cce021a7de9a0470d07176John Spurlock
560856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        public int getMinuteIndex() {
561856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            return mMinuteIndex;
562856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        }
563856edebad73560e9b1cce021a7de9a0470d07176John Spurlock
564856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        public void setMinuteIndex(int minuteIndex) {
565856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            minuteIndex = clamp(minuteIndex);
566856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            if (minuteIndex == mMinuteIndex) return;
567856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            mMinuteIndex = clamp(minuteIndex);
568856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            if (DEBUG) Log.d(mTag, "Setting favorite minute index: " + mMinuteIndex);
569856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            prefs().edit().putInt(KEY_MINUTE_INDEX, mMinuteIndex).apply();
570856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        }
571856edebad73560e9b1cce021a7de9a0470d07176John Spurlock
572856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        @Override
573856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
574856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            updateMinuteIndex();
575856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        }
576856edebad73560e9b1cce021a7de9a0470d07176John Spurlock
577856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        private SharedPreferences prefs() {
578856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            return mContext.getSharedPreferences(ZenModePanel.class.getSimpleName(), 0);
579856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        }
580856edebad73560e9b1cce021a7de9a0470d07176John Spurlock
581856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        private void updateMinuteIndex() {
582856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            mMinuteIndex = clamp(prefs().getInt(KEY_MINUTE_INDEX, DEFAULT_BUCKET_INDEX));
583856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            if (DEBUG) Log.d(mTag, "Favorite minute index: " + mMinuteIndex);
584856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        }
585856edebad73560e9b1cce021a7de9a0470d07176John Spurlock
586856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        private int clamp(int index) {
587856edebad73560e9b1cce021a7de9a0470d07176John Spurlock            return Math.max(-1, Math.min(MINUTE_BUCKETS.length - 1, index));
588856edebad73560e9b1cce021a7de9a0470d07176John Spurlock        }
589856edebad73560e9b1cce021a7de9a0470d07176John Spurlock    }
590ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock
591ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock    private final SegmentedButtons.Callback mZenButtonsCallback = new SegmentedButtons.Callback() {
592ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        @Override
593ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        public void onSelected(Object value) {
594ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock            if (value != null && mZenButtons.isShown()) {
595ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock                if (DEBUG) Log.d(mTag, "mZenButtonsCallback selected=" + value);
596ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock                mController.setZen((Integer) value);
597ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock                mController.setExitConditionId(null);
598ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock            }
599ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock        }
600ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock    };
6018600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock}
602