1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.tv.dvr.ui;
18 
19 import android.content.Context;
20 import android.content.Intent;
21 import android.graphics.drawable.Drawable;
22 import android.os.Bundle;
23 
24 import androidx.leanback.widget.GuidanceStylist;
25 import androidx.leanback.widget.GuidedAction;
26 
27 import com.android.tv.R;
28 import com.android.tv.TvSingletons;
29 import com.android.tv.data.ProgramImpl;
30 import com.android.tv.data.api.Program;
31 import com.android.tv.dvr.DvrScheduleManager;
32 import com.android.tv.dvr.data.ScheduledRecording;
33 import com.android.tv.dvr.data.SeriesRecording;
34 import com.android.tv.dvr.ui.list.DvrSchedulesActivity;
35 import com.android.tv.dvr.ui.list.DvrSeriesSchedulesFragment;
36 
37 import java.util.List;
38 
39 public class DvrSeriesScheduledFragment extends DvrGuidedStepFragment {
40     /**
41      * The key for program list which will be passed to {@link DvrSeriesSchedulesFragment}. Type:
42      * List<{@link ProgramImpl}>
43      */
44     public static final String SERIES_SCHEDULED_KEY_PROGRAMS = "series_scheduled_key_programs";
45 
46     private static final long SERIES_RECORDING_ID_NOT_SET = -1;
47 
48     private static final int ACTION_VIEW_SCHEDULES = 1;
49 
50     private SeriesRecording mSeriesRecording;
51     private boolean mShowViewScheduleOption;
52     private List<Program> mPrograms;
53     private String mSeriesRecordingTitle;
54 
55     private int mSchedulesAddedCount = 0;
56     private boolean mHasConflict = false;
57     private int mInThisSeriesConflictCount = 0;
58     private int mOutThisSeriesConflictCount = 0;
59 
60     @Override
onAttach(Context context)61     public void onAttach(Context context) {
62         super.onAttach(context);
63         long seriesRecordingId =
64                 getArguments()
65                         .getLong(
66                                 DvrSeriesScheduledDialogActivity.SERIES_RECORDING_ID,
67                                 SERIES_RECORDING_ID_NOT_SET);
68         if (seriesRecordingId == SERIES_RECORDING_ID_NOT_SET) {
69             getActivity().finish();
70             return;
71         }
72         mShowViewScheduleOption =
73                 getArguments()
74                         .getBoolean(DvrSeriesScheduledDialogActivity.SHOW_VIEW_SCHEDULE_OPTION);
75         mSeriesRecording =
76                 TvSingletons.getSingletons(context)
77                         .getDvrDataManager()
78                         .getSeriesRecording(seriesRecordingId);
79         if (mSeriesRecording == null) {
80             getActivity().finish();
81             return;
82         }
83         mSeriesRecordingTitle = mSeriesRecording.getTitle();
84         mPrograms = (List<Program>) BigArguments.getArgument(SERIES_SCHEDULED_KEY_PROGRAMS);
85         BigArguments.reset();
86         mSchedulesAddedCount =
87                 TvSingletons.getSingletons(getContext())
88                         .getDvrManager()
89                         .getAvailableScheduledRecording(mSeriesRecording.getId())
90                         .size();
91         DvrScheduleManager dvrScheduleManager =
92                 TvSingletons.getSingletons(context).getDvrScheduleManager();
93         List<ScheduledRecording> conflictingRecordings =
94                 dvrScheduleManager.getConflictingSchedules(mSeriesRecording);
95         mHasConflict = !conflictingRecordings.isEmpty();
96         for (ScheduledRecording recording : conflictingRecordings) {
97             if (recording.getSeriesRecordingId() == mSeriesRecording.getId()) {
98                 ++mInThisSeriesConflictCount;
99             } else if (recording.getPriority() < mSeriesRecording.getPriority()) {
100                 ++mOutThisSeriesConflictCount;
101             }
102         }
103     }
104 
105     @Override
onCreateGuidance(Bundle savedInstanceState)106     public GuidanceStylist.Guidance onCreateGuidance(Bundle savedInstanceState) {
107         String title = getString(R.string.dvr_series_recording_dialog_title);
108         Drawable icon;
109         if (!mHasConflict) {
110             icon = getResources().getDrawable(R.drawable.quantum_ic_check_circle_white_48, null);
111         } else {
112             icon = getResources().getDrawable(R.drawable.quantum_ic_error_white_48, null);
113         }
114         return new GuidanceStylist.Guidance(title, getDescription(), null, icon);
115     }
116 
117     @Override
onCreateActions(List<GuidedAction> actions, Bundle savedInstanceState)118     public void onCreateActions(List<GuidedAction> actions, Bundle savedInstanceState) {
119         Context context = getContext();
120         actions.add(
121                 new GuidedAction.Builder(context).clickAction(GuidedAction.ACTION_ID_OK).build());
122         if (mShowViewScheduleOption) {
123             actions.add(
124                     new GuidedAction.Builder(context)
125                             .id(ACTION_VIEW_SCHEDULES)
126                             .title(R.string.dvr_action_view_schedules)
127                             .build());
128         }
129     }
130 
131     @Override
onTrackedGuidedActionClicked(GuidedAction action)132     public void onTrackedGuidedActionClicked(GuidedAction action) {
133         if (action.getId() == ACTION_VIEW_SCHEDULES) {
134             Intent intent = new Intent(getActivity(), DvrSchedulesActivity.class);
135             intent.putExtra(
136                     DvrSchedulesActivity.KEY_SCHEDULES_TYPE,
137                     DvrSchedulesActivity.TYPE_SERIES_SCHEDULE);
138             intent.putExtra(
139                     DvrSeriesSchedulesFragment.SERIES_SCHEDULES_KEY_SERIES_RECORDING,
140                     mSeriesRecording);
141             BigArguments.reset();
142             BigArguments.setArgument(
143                     DvrSeriesSchedulesFragment.SERIES_SCHEDULES_KEY_SERIES_PROGRAMS, mPrograms);
144             startActivity(intent);
145         }
146         getActivity().finish();
147     }
148 
149     @Override
getTrackerPrefix()150     public String getTrackerPrefix() {
151         return "DvrMissingStorageErrorFragment";
152     }
153 
154     @Override
getTrackerLabelForGuidedAction(GuidedAction action)155     public String getTrackerLabelForGuidedAction(GuidedAction action) {
156         long actionId = action.getId();
157         if (actionId == ACTION_VIEW_SCHEDULES) {
158             return "view-schedules";
159         } else {
160             return super.getTrackerLabelForGuidedAction(action);
161         }
162     }
163 
getDescription()164     private String getDescription() {
165         if (!mHasConflict) {
166             return getResources()
167                     .getQuantityString(
168                             R.plurals.dvr_series_scheduled_no_conflict,
169                             mSchedulesAddedCount,
170                             mSchedulesAddedCount,
171                             mSeriesRecordingTitle);
172         } else {
173             // mInThisSeriesConflictCount equals 0 and mOutThisSeriesConflictCount equals 0 means
174             // mHasConflict is false. So we don't need to check that case.
175             if (mInThisSeriesConflictCount != 0 && mOutThisSeriesConflictCount != 0) {
176                 return getResources()
177                         .getQuantityString(
178                                 R.plurals.dvr_series_scheduled_this_and_other_series_conflict,
179                                 mSchedulesAddedCount,
180                                 mSchedulesAddedCount,
181                                 mSeriesRecordingTitle,
182                                 mInThisSeriesConflictCount + mOutThisSeriesConflictCount);
183             } else if (mInThisSeriesConflictCount != 0) {
184                 return getResources()
185                         .getQuantityString(
186                                 R.plurals.dvr_series_recording_scheduled_only_this_series_conflict,
187                                 mSchedulesAddedCount,
188                                 mSchedulesAddedCount,
189                                 mSeriesRecordingTitle,
190                                 mInThisSeriesConflictCount);
191             } else {
192                 if (mOutThisSeriesConflictCount == 1) {
193                     return getResources()
194                             .getQuantityString(
195                                     R.plurals.dvr_series_scheduled_only_other_series_one_conflict,
196                                     mSchedulesAddedCount,
197                                     mSchedulesAddedCount,
198                                     mSeriesRecordingTitle);
199                 } else {
200                     return getResources()
201                             .getQuantityString(
202                                     R.plurals.dvr_series_scheduled_only_other_series_many_conflicts,
203                                     mSchedulesAddedCount,
204                                     mSchedulesAddedCount,
205                                     mSeriesRecordingTitle,
206                                     mOutThisSeriesConflictCount);
207                 }
208             }
209         }
210     }
211 }
212