165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko/*
265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko* Copyright (C) 2016 The Android Open Source Project
365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko*
465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko* Licensed under the Apache License, Version 2.0 (the "License");
565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko* you may not use this file except in compliance with the License.
665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko* You may obtain a copy of the License at
765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko*
865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko*      http://www.apache.org/licenses/LICENSE-2.0
965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko*
1065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko* Unless required by applicable law or agreed to in writing, software
1165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko* distributed under the License is distributed on an "AS IS" BASIS,
1265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko* See the License for the specific language governing permissions and
1465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko* limitations under the License
1565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko*/
1665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
1765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkopackage com.android.tv.dvr.ui.list;
1865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
19d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalkoimport android.annotation.TargetApi;
2065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.content.Context;
21d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalkoimport android.media.tv.TvInputInfo;
22d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalkoimport android.os.Build;
2365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.support.v17.leanback.widget.ClassPresenterSelector;
24d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalkoimport android.util.ArrayMap;
25d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalkoimport android.util.Log;
2665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
27d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalkoimport com.android.tv.ApplicationSingletons;
2865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport com.android.tv.R;
2965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport com.android.tv.TvApplication;
3065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport com.android.tv.common.SoftPreconditions;
31d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalkoimport com.android.tv.data.Program;
32d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalkoimport com.android.tv.dvr.DvrDataManager;
3365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport com.android.tv.dvr.DvrManager;
346ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport com.android.tv.dvr.data.ScheduledRecording;
356ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport com.android.tv.dvr.data.SeriesRecording;
3665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport com.android.tv.dvr.ui.list.SchedulesHeaderRow.SeriesRecordingHeaderRow;
3765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport com.android.tv.util.Utils;
3865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
3965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport java.util.ArrayList;
4065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport java.util.Collections;
41d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalkoimport java.util.Iterator;
4265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport java.util.List;
43d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalkoimport java.util.Map;
4465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
4565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko/**
4665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * An adapter for series schedule row.
4765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */
48d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko@TargetApi(Build.VERSION_CODES.N)
496ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoclass SeriesScheduleRowAdapter extends ScheduleRowAdapter {
50d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    private static final String TAG = "SeriesRowAdapter";
51d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    private static final boolean DEBUG = false;
5265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
53d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    private final SeriesRecording mSeriesRecording;
54d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    private final String mInputId;
55d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    private final DvrManager mDvrManager;
56d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    private final DvrDataManager mDataManager;
57d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    private final Map<Long, Program> mPrograms = new ArrayMap<>();
58d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    private SeriesRecordingHeaderRow mHeaderRow;
5965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
60d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    public SeriesScheduleRowAdapter(Context context, ClassPresenterSelector classPresenterSelector,
61d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            SeriesRecording seriesRecording) {
6265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        super(context, classPresenterSelector);
6365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        mSeriesRecording = seriesRecording;
64d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        TvInputInfo input = Utils.getTvInputInfoForInputId(context, mSeriesRecording.getInputId());
65d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        if (SoftPreconditions.checkNotNull(input) != null) {
66d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            mInputId = input.getId();
67d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        } else {
68d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            mInputId = null;
69d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        }
70d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        ApplicationSingletons singletons = TvApplication.getSingletons(context);
71d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        mDvrManager = singletons.getDvrManager();
72d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        mDataManager = singletons.getDvrDataManager();
73d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        setHasStableIds(true);
7465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
7565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
7665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    @Override
7765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    public void start() {
78d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        setPrograms(Collections.emptyList());
79d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    }
80d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko
81d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    @Override
82d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    public void stop() {
83d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        super.stop();
84d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    }
85d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko
86d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    /**
87d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko     * Sets the programs to show.
88d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko     */
89d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    public void setPrograms(List<Program> programs) {
90d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        if (programs == null) {
91d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            programs = Collections.emptyList();
9265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
93d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        clear();
94d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        mPrograms.clear();
95d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        List<Program> sortedPrograms = new ArrayList<>(programs);
96d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        Collections.sort(sortedPrograms);
97d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        List<EpisodicProgramRow> rows = new ArrayList<>();
98d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        mHeaderRow = new SeriesRecordingHeaderRow(mSeriesRecording.getTitle(),
996ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                null, sortedPrograms.size(), mSeriesRecording, programs);
100d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        for (Program program : sortedPrograms) {
101d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            ScheduledRecording schedule =
102d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                    mDataManager.getScheduledRecordingForProgramId(program.getId());
103d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            if (schedule != null && !willBeKept(schedule)) {
104d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                schedule = null;
10565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            }
106d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            rows.add(new EpisodicProgramRow(mInputId, program, schedule, mHeaderRow));
107d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            mPrograms.put(program.getId(), program);
10865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
109d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        mHeaderRow.setDescription(getDescription());
110d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        add(mHeaderRow);
111d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        for (EpisodicProgramRow row : rows) {
112d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            add(row);
11365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
114d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        sendNextUpdateMessage(System.currentTimeMillis());
115d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    }
116d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko
117d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    private String getDescription() {
118d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        int conflicts = 0;
119d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        for (long programId : mPrograms.keySet()) {
120d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            if (mDvrManager.isConflicting(
121d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                    mDataManager.getScheduledRecordingForProgramId(programId))) {
122d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                ++conflicts;
123d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            }
12465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
125d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        return conflicts == 0 ? null : getContext().getResources().getQuantityString(
126d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                R.plurals.dvr_series_schedules_header_description, conflicts, conflicts);
12765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
12865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
12965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    @Override
130d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    public long getId(int position) {
131d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        Object obj = get(position);
132d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        if (obj instanceof EpisodicProgramRow) {
133d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            return ((EpisodicProgramRow) obj).getProgram().getId();
134d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        }
135d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        if (obj instanceof SeriesRecordingHeaderRow) {
136d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            return 0;
137d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        }
138d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        return super.getId(position);
139d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    }
140d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko
141d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    @Override
142d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    public void onScheduledRecordingAdded(ScheduledRecording schedule) {
143d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        if (DEBUG) Log.d(TAG, "onScheduledRecordingAdded: " + schedule);
144d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        int index = findRowIndexByProgramId(schedule.getProgramId());
145d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        if (index != -1) {
146d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            EpisodicProgramRow row = (EpisodicProgramRow) get(index);
147d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            if (!row.isStartRecordingRequested()) {
1486ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                setScheduleToRow(row, schedule);
149d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                notifyArrayItemRangeChanged(index, 1);
15065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            }
15165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
15265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
15365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
15465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    @Override
155d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    public void onScheduledRecordingRemoved(ScheduledRecording schedule) {
156d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        if (DEBUG) Log.d(TAG, "onScheduledRecordingRemoved: " + schedule);
157d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        int index = findRowIndexByProgramId(schedule.getProgramId());
158d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        if (index != -1) {
159d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            EpisodicProgramRow row = (EpisodicProgramRow) get(index);
160d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            row.setSchedule(null);
161d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            notifyArrayItemRangeChanged(index, 1);
162d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        }
163d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    }
164d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko
165d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    @Override
166d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    public void onScheduledRecordingUpdated(ScheduledRecording schedule, boolean conflictChange) {
167d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        if (DEBUG) Log.d(TAG, "onScheduledRecordingUpdated: " + schedule);
168d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        int index = findRowIndexByProgramId(schedule.getProgramId());
169d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        if (index != -1) {
170d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            EpisodicProgramRow row = (EpisodicProgramRow) get(index);
171d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            if (conflictChange && isStartOrStopRequested()) {
172d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                // Delay the conflict update until it gets the response of the start/stop request.
173d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                // The purpose is to avoid the intermediate conflict change.
174d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                addPendingUpdate(row);
175d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                return;
176d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            }
177d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            if (row.isStopRecordingRequested()) {
178d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                // Wait until the recording is finished
179d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                if (schedule.getState() == ScheduledRecording.STATE_RECORDING_FINISHED
180d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                        || schedule.getState() == ScheduledRecording.STATE_RECORDING_CLIPPED
181d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                        || schedule.getState() == ScheduledRecording.STATE_RECORDING_FAILED) {
182d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                    row.setStopRecordingRequested(false);
183d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                    if (!isStartOrStopRequested()) {
184d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                        executePendingUpdate();
18565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                    }
186d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                    row.setSchedule(null);
18765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                }
188d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            } else if (row.isStartRecordingRequested()) {
189d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                // When the start recording was requested, we give the highest priority. So it is
190d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                // guaranteed that the state will be changed from NOT_STARTED to the other state.
191d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                // Update the row with the next state not to show the intermediate state to avoid
192d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                // blinking.
193d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                if (schedule.getState() != ScheduledRecording.STATE_RECORDING_NOT_STARTED) {
194d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                    row.setStartRecordingRequested(false);
195d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                    if (!isStartOrStopRequested()) {
196d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                        executePendingUpdate();
197d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                    }
1986ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                    setScheduleToRow(row, schedule);
199d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                }
200d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            } else {
2016ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                setScheduleToRow(row, schedule);
20265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            }
203d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            notifyArrayItemRangeChanged(index, 1);
20465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
20565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
20665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
207d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    public void onSeriesRecordingUpdated(SeriesRecording seriesRecording) {
208d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        if (seriesRecording.getId() == mSeriesRecording.getId()) {
209d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            mHeaderRow.setSeriesRecording(seriesRecording);
210d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            notifyArrayItemRangeChanged(0, 1);
211d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        }
212d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    }
213d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko
2146ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    private void setScheduleToRow(ScheduleRow row, ScheduledRecording schedule) {
2156ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        if (schedule != null && willBeKept(schedule)) {
2166ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            row.setSchedule(schedule);
2176ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        } else {
2186ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            row.setSchedule(null);
2196ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        }
2206ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    }
2216ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko
222d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    private int findRowIndexByProgramId(long programId) {
223d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        for (int i = 0; i < size(); i++) {
224d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            Object item = get(i);
225d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            if (item instanceof EpisodicProgramRow) {
226d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                if (((EpisodicProgramRow) item).getProgram().getId() == programId) {
227d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                    return i;
22865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                }
22965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            }
23065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
231d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        return -1;
23265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
23365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
23465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    @Override
235d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    public void notifyArrayItemRangeChanged(int positionStart, int itemCount) {
236d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        mHeaderRow.setDescription(getDescription());
237d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        super.notifyArrayItemRangeChanged(0, 1);
238d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        super.notifyArrayItemRangeChanged(positionStart, itemCount);
23965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
24065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
241d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    @Override
242d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    protected void handleUpdateRow(long currentTimeMs) {
243d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        for (Iterator<Program> iter = mPrograms.values().iterator(); iter.hasNext(); ) {
244d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            Program program = iter.next();
245d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            if (program.getEndTimeUtcMillis() <= currentTimeMs) {
246d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                // Remove the old program.
247d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                removeItems(findRowIndexByProgramId(program.getId()), 1);
248d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                iter.remove();
249d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            } else if (program.getStartTimeUtcMillis() < currentTimeMs) {
250d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                // Change the button "START RECORDING"
251d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                notifyItemRangeChanged(findRowIndexByProgramId(program.getId()), 1);
252d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            }
253d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        }
254d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    }
255d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko
256d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    /**
257d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko     * Should take the current time argument which is the time when the programs are checked in
258d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko     * handler.
259d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko     */
260d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    @Override
261d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    protected long getNextTimerMs(long currentTimeMs) {
262d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        long earliest = Long.MAX_VALUE;
263d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        for (Program program : mPrograms.values()) {
264d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            if (earliest > program.getStartTimeUtcMillis()
265d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                    && program.getStartTimeUtcMillis() >= currentTimeMs) {
266d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                // Need the button from "CREATE SCHEDULE" to "START RECORDING"
267d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                earliest = program.getStartTimeUtcMillis();
268d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            } else if (earliest > program.getEndTimeUtcMillis()) {
269d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                // Need to remove the row.
270d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                earliest = program.getEndTimeUtcMillis();
271d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            }
272d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        }
273d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        return earliest;
27465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
27565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko}
276