Settings: Improve automatic rule summary when enabled.

Bug: 20064962
Change-Id: I139679def84f0ba3ea859399499a5657fd85e763
diff --git a/res/values/strings.xml b/res/values/strings.xml
index b6ec685..940f6bf 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -5867,17 +5867,26 @@
     <!-- [CHAR LIMIT=40] Zen mode settings: Text to display if rule isn't found  -->
     <string name="zen_mode_rule_not_found_text">Rule not found.</string>
 
+    <!-- [CHAR LIMIT=40] Zen mode settings: Rule summary template (when enabled)  -->
+    <string name="zen_mode_rule_summary_template"><xliff:g id="days" example="Sun - Thu">%1$s</xliff:g> / <xliff:g id="timerange" example="10:00 PM to 7:30 AM">%2$s</xliff:g> / <xliff:g id="mode" example="Alarms only">%3$s</xliff:g></string>
+
     <!-- [CHAR LIMIT=40] Zen mode settings: Timebased rule days option title -->
     <string name="zen_mode_schedule_rule_days">Days</string>
 
     <!-- [CHAR LIMIT=40] Zen mode settings: Downtime days option value, no days set -->
     <string name="zen_mode_schedule_rule_days_none">None</string>
 
+    <!-- [CHAR LIMIT=40] Zen mode settings: Downtime days option value, all days set -->
+    <string name="zen_mode_schedule_rule_days_all">Every day</string>
+
     <!-- [CHAR LIMIT=40] General divider text when concatenating multiple items in a text summary -->
     <string name="summary_divider_text">,\u0020</string>
 
-    <!-- [CHAR LIMIT=40] Zen mode settings: Entry conditions option: value when blank -->
-    <string name="zen_mode_entry_conditions_summary_none">Never</string>
+    <!-- [CHAR LIMIT=40] General template for a symbolic start - end range in a text summary -->
+    <string name="summary_range_symbol_combination"><xliff:g id="start" example="Sun">%1$s</xliff:g> - <xliff:g id="end" example="Thu">%2$s</xliff:g></string>
+
+    <!-- [CHAR LIMIT=40] General template for a verbal start to end range in a text summary -->
+    <string name="summary_range_verbal_combination"><xliff:g id="start" example="Sun">%1$s</xliff:g> to <xliff:g id="end" example="Thu">%2$s</xliff:g></string>
 
     <!-- [CHAR LIMIT=20] Zen mode settings: Calls option -->
     <string name="zen_mode_calls">Calls</string>
diff --git a/src/com/android/settings/notification/ZenModeAutomationSettings.java b/src/com/android/settings/notification/ZenModeAutomationSettings.java
index 09de7d1..c43d99e 100644
--- a/src/com/android/settings/notification/ZenModeAutomationSettings.java
+++ b/src/com/android/settings/notification/ZenModeAutomationSettings.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.notification;
 
+import static android.service.notification.ZenModeConfig.ALL_DAYS;
+
 import android.content.Intent;
 import android.os.Bundle;
 import android.preference.Preference;
@@ -25,6 +27,7 @@
 import android.service.notification.ZenModeConfig;
 import android.service.notification.ZenModeConfig.ScheduleInfo;
 import android.service.notification.ZenModeConfig.ZenRule;
+import android.text.format.DateFormat;
 import android.util.Log;
 import android.view.Menu;
 import android.view.MenuInflater;
@@ -33,7 +36,14 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.settings.R;
 
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.TreeSet;
+
 public class ZenModeAutomationSettings extends ZenModeSettingsBase {
+    private static final SimpleDateFormat DAY_FORMAT = new SimpleDateFormat("EEE");
+
+    private final Calendar mCalendar = Calendar.getInstance();
 
     @Override
     public void onCreate(Bundle icicle) {
@@ -115,7 +125,7 @@
             if (!ZenModeConfig.isValidScheduleConditionId(rule.conditionId)) continue;
             final Preference p = new Preference(mContext);
             p.setTitle(rule.name);
-            p.setSummary(rule.enabled ? R.string.switch_on_text : R.string.switch_off_text);
+            p.setSummary(computeRuleSummary(rule));
             p.setPersistent(false);
             p.setOnPreferenceClickListener(new OnPreferenceClickListener() {
                 @Override
@@ -133,4 +143,60 @@
         return MetricsLogger.NOTIFICATION_ZEN_MODE_AUTOMATION;
     }
 
+    private String computeRuleSummary(ZenRule rule) {
+        if (rule == null || !rule.enabled) return getString(R.string.switch_off_text);
+        final ScheduleInfo schedule = ZenModeConfig.tryParseScheduleConditionId(rule.conditionId);
+        if (schedule == null) return getString(R.string.switch_on_text);
+        final String days = computeContiguousDayRanges(schedule.days);
+        final String start = getTime(schedule.startHour, schedule.startMinute);
+        final String end = getTime(schedule.endHour, schedule.endMinute);
+        final String time = getString(R.string.summary_range_verbal_combination, start, end);
+        final String mode = ZenModeSettings.computeZenModeCaption(getResources(), rule.zenMode);
+        return getString(R.string.zen_mode_rule_summary_template, days, time, mode);
+    }
+
+    private String getTime(int hour, int minute) {
+        mCalendar.set(Calendar.HOUR_OF_DAY, hour);
+        mCalendar.set(Calendar.MINUTE, minute);
+        return DateFormat.getTimeFormat(mContext).format(mCalendar.getTime());
+    }
+
+    private String computeContiguousDayRanges(int[] days) {
+        final TreeSet<Integer> daySet = new TreeSet<>();
+        for (int i = 0; days != null && i < days.length; i++) {
+            daySet.add(days[i]);
+        }
+        if (daySet.isEmpty()) {
+            return getString(R.string.zen_mode_schedule_rule_days_none);
+        }
+        final int N = ALL_DAYS.length;
+        if (daySet.size() == N) {
+            return getString(R.string.zen_mode_schedule_rule_days_all);
+        }
+        String rt = null;
+        for (int i = 0; i < N; i++) {
+            final int startDay = ALL_DAYS[i];
+            final boolean active = daySet.contains(startDay);
+            if (!active) continue;
+            int end = 0;
+            while (daySet.contains(ALL_DAYS[(i + end + 1) % N])) {
+                end++;
+            }
+            if (!(i == 0 && daySet.contains(ALL_DAYS[N - 1]))) {
+                final String v = end == 0 ? dayString(startDay)
+                        : getString(R.string.summary_range_symbol_combination,
+                                dayString(startDay),
+                                dayString(ALL_DAYS[(i + end) % N]));
+                rt = rt == null ? v : getString(R.string.summary_divider_text, rt, v);
+            }
+            i += end;
+        }
+        return rt;
+    }
+
+    private String dayString(int day) {
+        mCalendar.set(Calendar.DAY_OF_WEEK, day);
+        return DAY_FORMAT.format(mCalendar.getTime());
+    }
+
 }
diff --git a/src/com/android/settings/notification/ZenModeScheduleRuleSettings.java b/src/com/android/settings/notification/ZenModeScheduleRuleSettings.java
index 7bec3c4..f0f0294 100644
--- a/src/com/android/settings/notification/ZenModeScheduleRuleSettings.java
+++ b/src/com/android/settings/notification/ZenModeScheduleRuleSettings.java
@@ -209,8 +209,8 @@
                     return true;
                 }
                 if (DEBUG) Log.d(TAG, "onPrefChange end h=" + hour + " m=" + minute);
-                mSchedule.startHour = hour;
-                mSchedule.startMinute = minute;
+                mSchedule.endHour = hour;
+                mSchedule.endMinute = minute;
                 mRule.conditionId = ZenModeConfig.toScheduleConditionId(mSchedule);
                 mRule.condition = null;
                 mRule.snoozing = false;
diff --git a/src/com/android/settings/notification/ZenModeSettings.java b/src/com/android/settings/notification/ZenModeSettings.java
index 4ff5e0f..88ecef5 100644
--- a/src/com/android/settings/notification/ZenModeSettings.java
+++ b/src/com/android/settings/notification/ZenModeSettings.java
@@ -126,21 +126,21 @@
         updateControls();
     }
 
-    private String computeZenModeCaption(int zenMode) {
+    public static String computeZenModeCaption(Resources res, int zenMode) {
         switch (zenMode) {
             case Global.ZEN_MODE_ALARMS:
-                return getString(R.string.zen_mode_option_alarms);
+                return res.getString(R.string.zen_mode_option_alarms);
             case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
-                return getString(R.string.zen_mode_option_important_interruptions);
+                return res.getString(R.string.zen_mode_option_important_interruptions);
             case Global.ZEN_MODE_NO_INTERRUPTIONS:
-                return getString(R.string.zen_mode_option_no_interruptions);
+                return res.getString(R.string.zen_mode_option_no_interruptions);
             default:
                 return null;
         }
     }
 
     private String computeZenModeSummaryLine() {
-        final String caption = computeZenModeCaption(mZenMode);
+        final String caption = computeZenModeCaption(getResources(), mZenMode);
         if (caption == null) return null;  // zen mode off
         final String conditionText = ZenModeConfig.getConditionLine1(mContext, mConfig,
                 UserHandle.myUserId());
@@ -190,7 +190,7 @@
         ScrollView scrollView = new ScrollView(mContext);
         scrollView.addView(zenModeConditionSelection);
         mDialog = new AlertDialog.Builder(getActivity())
-                .setTitle(computeZenModeCaption(zenMode))
+                .setTitle(computeZenModeCaption(getResources(), zenMode))
                 .setView(scrollView)
                 .setPositiveButton(R.string.okay, positiveListener)
                 .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {