1ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko/*
2ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko * Copyright (C) 2015 The Android Open Source Project
3ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko *
4ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko * Licensed under the Apache License, Version 2.0 (the "License");
5ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko * you may not use this file except in compliance with the License.
6ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko * You may obtain a copy of the License at
7ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko *
8ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko *      http://www.apache.org/licenses/LICENSE-2.0
9ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko *
10ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko * Unless required by applicable law or agreed to in writing, software
11ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko * distributed under the License is distributed on an "AS IS" BASIS,
12ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko * See the License for the specific language governing permissions and
14ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko * limitations under the License
15ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko */
16ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko
176ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkopackage com.android.tv.dvr.ui.browse;
18ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko
1965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.content.Context;
20ba5845f23b8fbc985890f892961abc8b39886611Nick Chalkoimport android.os.Bundle;
2165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.os.Handler;
22ba5845f23b8fbc985890f892961abc8b39886611Nick Chalkoimport android.support.v17.leanback.app.BrowseFragment;
23ba5845f23b8fbc985890f892961abc8b39886611Nick Chalkoimport android.support.v17.leanback.widget.ArrayObjectAdapter;
242e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalkoimport android.support.v17.leanback.widget.ClassPresenterSelector;
25ba5845f23b8fbc985890f892961abc8b39886611Nick Chalkoimport android.support.v17.leanback.widget.HeaderItem;
26ba5845f23b8fbc985890f892961abc8b39886611Nick Chalkoimport android.support.v17.leanback.widget.ListRow;
27d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalkoimport android.support.v17.leanback.widget.Presenter;
2865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.support.v17.leanback.widget.TitleViewAdapter;
29ba5845f23b8fbc985890f892961abc8b39886611Nick Chalkoimport android.util.Log;
306ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport android.view.View;
316ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport android.view.ViewTreeObserver.OnGlobalFocusChangeListener;
32ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko
33d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalkoimport com.android.tv.ApplicationSingletons;
34ba5845f23b8fbc985890f892961abc8b39886611Nick Chalkoimport com.android.tv.R;
35ba5845f23b8fbc985890f892961abc8b39886611Nick Chalkoimport com.android.tv.TvApplication;
3665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport com.android.tv.data.GenreItems;
37ba5845f23b8fbc985890f892961abc8b39886611Nick Chalkoimport com.android.tv.dvr.DvrDataManager;
3865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport com.android.tv.dvr.DvrDataManager.OnDvrScheduleLoadFinishedListener;
3965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport com.android.tv.dvr.DvrDataManager.OnRecordedProgramLoadFinishedListener;
40d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalkoimport com.android.tv.dvr.DvrDataManager.RecordedProgramListener;
41d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalkoimport com.android.tv.dvr.DvrDataManager.ScheduledRecordingListener;
42d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalkoimport com.android.tv.dvr.DvrDataManager.SeriesRecordingListener;
43d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalkoimport com.android.tv.dvr.DvrScheduleManager;
446ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport com.android.tv.dvr.data.RecordedProgram;
456ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport com.android.tv.dvr.data.ScheduledRecording;
466ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport com.android.tv.dvr.data.SeriesRecording;
476ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport com.android.tv.dvr.ui.SortedArrayAdapter;
48ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko
4965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport java.util.ArrayList;
5065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport java.util.Arrays;
5165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport java.util.Comparator;
5265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport java.util.HashMap;
5365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport java.util.List;
54ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko
55ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko/**
56ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko * {@link BrowseFragment} for DVR functions.
57ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko */
5865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkopublic class DvrBrowseFragment extends BrowseFragment implements
5965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        RecordedProgramListener, ScheduledRecordingListener, SeriesRecordingListener,
6065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        OnDvrScheduleLoadFinishedListener, OnRecordedProgramLoadFinishedListener {
61ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    private static final String TAG = "DvrBrowseFragment";
622e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko    private static final boolean DEBUG = false;
632e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko
6465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private static final int MAX_RECENT_ITEM_COUNT = 10;
6565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private static final int MAX_SCHEDULED_ITEM_COUNT = 4;
66ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko
676ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    private boolean mShouldShowScheduleRow;
686ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    private boolean mEntranceTransitionEnded;
696ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko
7065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private RecordedProgramAdapter mRecentAdapter;
7165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private ScheduleAdapter mScheduleAdapter;
72d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    private SeriesAdapter mSeriesAdapter;
7365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private RecordedProgramAdapter[] mGenreAdapters =
7465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            new RecordedProgramAdapter[GenreItems.getGenreCount() + 1];
7565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private ListRow mRecentRow;
766ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    private ListRow mScheduledRow;
7765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private ListRow mSeriesRow;
7865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private ListRow[] mGenreRows = new ListRow[GenreItems.getGenreCount() + 1];
7965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private List<String> mGenreLabels;
80ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    private DvrDataManager mDvrDataManager;
81d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    private DvrScheduleManager mDvrScheudleManager;
82ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    private ArrayObjectAdapter mRowsAdapter;
8365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private ClassPresenterSelector mPresenterSelector;
8465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private final HashMap<String, RecordedProgram> mSeriesId2LatestProgram = new HashMap<>();
8565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private final Handler mHandler = new Handler();
866ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    private final OnGlobalFocusChangeListener mOnGlobalFocusChangeListener =
876ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            new OnGlobalFocusChangeListener() {
886ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                @Override
896ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                public void onGlobalFocusChanged(View oldFocus, View newFocus) {
906ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                    if (oldFocus instanceof RecordingCardView) {
916ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                        ((RecordingCardView) oldFocus).expandTitle(false, true);
926ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                    }
936ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                    if (newFocus instanceof RecordingCardView) {
946ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                        // If the header transition is ongoing, expand cards immediately without
956ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                        // animation to make a smooth transition.
966ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                        ((RecordingCardView) newFocus).expandTitle(true, !isInHeadersTransition());
976ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                    }
986ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                }
996ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            };
10065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
10165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private final Comparator<Object> RECORDED_PROGRAM_COMPARATOR = new Comparator<Object>() {
10265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        @Override
10365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        public int compare(Object lhs, Object rhs) {
10465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            if (lhs instanceof SeriesRecording) {
10565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                lhs = mSeriesId2LatestProgram.get(((SeriesRecording) lhs).getSeriesId());
10665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            }
10765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            if (rhs instanceof SeriesRecording) {
10865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                rhs = mSeriesId2LatestProgram.get(((SeriesRecording) rhs).getSeriesId());
10965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            }
11065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            if (lhs instanceof RecordedProgram) {
11165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                if (rhs instanceof RecordedProgram) {
11265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                    return RecordedProgram.START_TIME_THEN_ID_COMPARATOR.reversed()
11365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                            .compare((RecordedProgram) lhs, (RecordedProgram) rhs);
11465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                } else {
11565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                    return -1;
11665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                }
11765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            } else if (rhs instanceof RecordedProgram) {
11865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                return 1;
11965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            } else {
12065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                return 0;
12165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            }
12265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
12365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    };
12465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
1256ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    private static final Comparator<Object> SCHEDULE_COMPARATOR = new Comparator<Object>() {
12665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        @Override
12765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        public int compare(Object lhs, Object rhs) {
12865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            if (lhs instanceof ScheduledRecording) {
12965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                if (rhs instanceof ScheduledRecording) {
130d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                    return ScheduledRecording.START_TIME_THEN_PRIORITY_THEN_ID_COMPARATOR
13165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                            .compare((ScheduledRecording) lhs, (ScheduledRecording) rhs);
13265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                } else {
13365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                    return -1;
13465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                }
13565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            } else if (rhs instanceof ScheduledRecording) {
13665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                return 1;
13765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            } else {
13865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                return 0;
13965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            }
14065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
14165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    };
14265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
143d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    private final DvrScheduleManager.OnConflictStateChangeListener mOnConflictStateChangeListener =
144d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            new DvrScheduleManager.OnConflictStateChangeListener() {
14565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        @Override
146d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        public void onConflictStateChange(boolean conflict, ScheduledRecording... schedules) {
147d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            if (mScheduleAdapter != null) {
148d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                for (ScheduledRecording schedule : schedules) {
1496ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                    onScheduledRecordingConflictStatusChanged(schedule);
15065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                }
15165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            }
15265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
15365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    };
15465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
15565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private final Runnable mUpdateRowsRunnable = new Runnable() {
15665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        @Override
15765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        public void run() {
15865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            updateRows();
15965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
16065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    };
161ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko
162ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    @Override
1632e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko    public void onCreate(Bundle savedInstanceState) {
1642e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko        if (DEBUG) Log.d(TAG, "onCreate");
1652e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko        super.onCreate(savedInstanceState);
16665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        Context context = getContext();
167d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        ApplicationSingletons singletons = TvApplication.getSingletons(context);
168d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        mDvrDataManager = singletons.getDvrDataManager();
169d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        mDvrScheudleManager = singletons.getDvrScheduleManager();
17065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        mPresenterSelector = new ClassPresenterSelector()
17165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                .addClassPresenter(ScheduledRecording.class,
17265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                        new ScheduledRecordingPresenter(context))
17365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                .addClassPresenter(RecordedProgram.class, new RecordedProgramPresenter(context))
17465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                .addClassPresenter(SeriesRecording.class, new SeriesRecordingPresenter(context))
1756ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                .addClassPresenter(FullScheduleCardHolder.class,
1766ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                        new FullSchedulesCardPresenter(context));
17765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        mGenreLabels = new ArrayList<>(Arrays.asList(GenreItems.getLabels(context)));
17865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        mGenreLabels.add(getString(R.string.dvr_main_others));
1796ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        prepareUiElements();
1806ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        if (!startBrowseIfDvrInitialized()) {
18165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            if (!mDvrDataManager.isDvrScheduleLoadFinished()) {
18265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                mDvrDataManager.addDvrScheduleLoadFinishedListener(this);
18365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            }
18465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            if (!mDvrDataManager.isRecordedProgramLoadFinished()) {
18565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                mDvrDataManager.addRecordedProgramLoadFinishedListener(this);
18665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            }
18765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
1882e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko    }
1892e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko
1902e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko    @Override
1916ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    public void onViewCreated(View view, Bundle savedInstanceState) {
1926ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        super.onViewCreated(view, savedInstanceState);
1936ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        view.getViewTreeObserver().addOnGlobalFocusChangeListener(mOnGlobalFocusChangeListener);
1946ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    }
1956ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko
1966ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    @Override
1976ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    public void onDestroyView() {
1986ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        getView().getViewTreeObserver()
1996ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                .removeOnGlobalFocusChangeListener(mOnGlobalFocusChangeListener);
2006ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        super.onDestroyView();
2016ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    }
2026ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko
2036ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    @Override
2042e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko    public void onDestroy() {
2052e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko        if (DEBUG) Log.d(TAG, "onDestroy");
20665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        mHandler.removeCallbacks(mUpdateRowsRunnable);
207d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        mDvrScheudleManager.removeOnConflictStateChangeListener(mOnConflictStateChangeListener);
20865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        mDvrDataManager.removeRecordedProgramListener(this);
20965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        mDvrDataManager.removeScheduledRecordingListener(this);
21065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        mDvrDataManager.removeSeriesRecordingListener(this);
21165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        mDvrDataManager.removeDvrScheduleLoadFinishedListener(this);
21265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        mDvrDataManager.removeRecordedProgramLoadFinishedListener(this);
21365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        mRowsAdapter.clear();
21465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        mSeriesId2LatestProgram.clear();
215d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        for (Presenter presenter : mPresenterSelector.getPresenters()) {
216d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            if (presenter instanceof DvrItemPresenter) {
217d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                ((DvrItemPresenter) presenter).unbindAllViewHolders();
218d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            }
219d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        }
220d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        super.onDestroy();
22165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
22265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
22365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    @Override
22465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    public void onDvrScheduleLoadFinished() {
2256ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        startBrowseIfDvrInitialized();
22665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        mDvrDataManager.removeDvrScheduleLoadFinishedListener(this);
22765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
22865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
22965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    @Override
23065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    public void onRecordedProgramLoadFinished() {
2316ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        startBrowseIfDvrInitialized();
23265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        mDvrDataManager.removeRecordedProgramLoadFinishedListener(this);
23365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
23465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
23565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    @Override
236d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    public void onRecordedProgramsAdded(RecordedProgram... recordedPrograms) {
237d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        for (RecordedProgram recordedProgram : recordedPrograms) {
23865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            handleRecordedProgramAdded(recordedProgram, true);
23965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
240d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        postUpdateRows();
24165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
24265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
24365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    @Override
244d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    public void onRecordedProgramsChanged(RecordedProgram... recordedPrograms) {
245d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        for (RecordedProgram recordedProgram : recordedPrograms) {
24665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            handleRecordedProgramChanged(recordedProgram);
24765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
248d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        postUpdateRows();
24965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
25065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
25165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    @Override
252d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    public void onRecordedProgramsRemoved(RecordedProgram... recordedPrograms) {
253d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        for (RecordedProgram recordedProgram : recordedPrograms) {
25465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            handleRecordedProgramRemoved(recordedProgram);
25565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
256d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        postUpdateRows();
25765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
25865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
25965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    // No need to call updateRows() during ScheduledRecordings' change because
26065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    // the row for ScheduledRecordings is always displayed.
26165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    @Override
26265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    public void onScheduledRecordingAdded(ScheduledRecording... scheduledRecordings) {
26365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        for (ScheduledRecording scheduleRecording : scheduledRecordings) {
26465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            if (needToShowScheduledRecording(scheduleRecording)) {
26565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                mScheduleAdapter.add(scheduleRecording);
26665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            }
26765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
26865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
26965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
27065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    @Override
27165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    public void onScheduledRecordingRemoved(ScheduledRecording... scheduledRecordings) {
27265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        for (ScheduledRecording scheduleRecording : scheduledRecordings) {
27365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            mScheduleAdapter.remove(scheduleRecording);
27465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
27565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
27665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
27765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    @Override
27865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    public void onScheduledRecordingStatusChanged(ScheduledRecording... scheduledRecordings) {
27965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        for (ScheduledRecording scheduleRecording : scheduledRecordings) {
28065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            if (needToShowScheduledRecording(scheduleRecording)) {
28165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                mScheduleAdapter.change(scheduleRecording);
28265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            } else {
28365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                mScheduleAdapter.removeWithId(scheduleRecording);
28465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            }
28565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
28665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
28765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
2886ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    private void onScheduledRecordingConflictStatusChanged(ScheduledRecording... schedules) {
2896ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        for (ScheduledRecording schedule : schedules) {
2906ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            if (needToShowScheduledRecording(schedule)) {
2916ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                if (mScheduleAdapter.contains(schedule)) {
2926ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                    mScheduleAdapter.change(schedule);
2936ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                }
2946ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            } else {
2956ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                mScheduleAdapter.removeWithId(schedule);
2966ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            }
2976ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        }
2986ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    }
2996ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko
30065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    @Override
30165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    public void onSeriesRecordingAdded(SeriesRecording... seriesRecordings) {
30265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        handleSeriesRecordingsAdded(Arrays.asList(seriesRecordings));
30365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        postUpdateRows();
30465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
30565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
30665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    @Override
30765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    public void onSeriesRecordingRemoved(SeriesRecording... seriesRecordings) {
30865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        handleSeriesRecordingsRemoved(Arrays.asList(seriesRecordings));
30965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        postUpdateRows();
31065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
31165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
31265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    @Override
31365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    public void onSeriesRecordingChanged(SeriesRecording... seriesRecordings) {
31465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        handleSeriesRecordingsChanged(Arrays.asList(seriesRecordings));
31565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        postUpdateRows();
31665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
31765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
31865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    // Workaround of b/29108300
31965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    @Override
32065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    public void showTitle(int flags) {
32165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        flags &= ~TitleViewAdapter.SEARCH_VIEW_VISIBLE;
32265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        super.showTitle(flags);
323ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    }
324ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko
3256ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    @Override
3266ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    protected void onEntranceTransitionEnd() {
3276ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        super.onEntranceTransitionEnd();
3286ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        if (mShouldShowScheduleRow) {
3296ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            showScheduledRowInternal();
3306ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        }
3316ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        mEntranceTransitionEnded = true;
3326ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    }
3336ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko
3346ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    void showScheduledRow() {
3356ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        if (!mEntranceTransitionEnded) {
3366ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            setHeadersState(HEADERS_HIDDEN);
3376ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            mShouldShowScheduleRow = true;
3386ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        } else {
3396ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            showScheduledRowInternal();
3406ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        }
3416ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    }
3426ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko
3436ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    private void showScheduledRowInternal() {
3446ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        setSelectedPosition(mRowsAdapter.indexOf(mScheduledRow), true, null);
3456ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        if (getHeadersState() == HEADERS_ENABLED) {
3466ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            startHeadersTransition(false);
3476ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        }
3486ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        mShouldShowScheduleRow = false;
3496ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    }
3506ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko
3516ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    private void prepareUiElements() {
35265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        setBadgeDrawable(getActivity().getDrawable(R.drawable.ic_dvr_badge));
353ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        setHeadersState(HEADERS_ENABLED);
354ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        setHeadersTransitionOnBackEnabled(false);
35565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        setBrandColor(getResources().getColor(R.color.program_guide_side_panel_background, null));
3566ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        mRowsAdapter = new ArrayObjectAdapter(new DvrListRowPresenter(getContext()));
3576ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        setAdapter(mRowsAdapter);
3586ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        prepareEntranceTransition();
359ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    }
360ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko
3616ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko    private boolean startBrowseIfDvrInitialized() {
3626ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        if (mDvrDataManager.isInitialized()) {
3636ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            // Setup rows
3646ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            mRecentAdapter = new RecordedProgramAdapter(MAX_RECENT_ITEM_COUNT);
3656ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            mScheduleAdapter = new ScheduleAdapter(MAX_SCHEDULED_ITEM_COUNT);
3666ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            mSeriesAdapter = new SeriesAdapter();
3676ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            for (int i = 0; i < mGenreAdapters.length; i++) {
3686ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                mGenreAdapters[i] = new RecordedProgramAdapter();
3696ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            }
3706ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            // Schedule Recordings.
3716ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            List<ScheduledRecording> schedules = mDvrDataManager.getAllScheduledRecordings();
3726ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            onScheduledRecordingAdded(ScheduledRecording.toArray(schedules));
3736ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            mScheduleAdapter.addExtraItem(FullScheduleCardHolder.FULL_SCHEDULE_CARD_HOLDER);
3746ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            // Recorded Programs.
3756ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            for (RecordedProgram recordedProgram : mDvrDataManager.getRecordedPrograms()) {
3766ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                handleRecordedProgramAdded(recordedProgram, false);
3776ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            }
3786ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            // Series Recordings. Series recordings should be added after recorded programs, because
3796ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            // we build series recordings' latest program information while adding recorded programs.
3806ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            List<SeriesRecording> recordings = mDvrDataManager.getSeriesRecordings();
3816ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            handleSeriesRecordingsAdded(recordings);
3826ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            mRecentRow = new ListRow(new HeaderItem(
3836ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                    getString(R.string.dvr_main_recent)), mRecentAdapter);
3846ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            mScheduledRow = new ListRow(new HeaderItem(
3856ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                    getString(R.string.dvr_main_scheduled)), mScheduleAdapter);
3866ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            mSeriesRow = new ListRow(new HeaderItem(
3876ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                    getString(R.string.dvr_main_series)), mSeriesAdapter);
3886ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            mRowsAdapter.add(mScheduledRow);
3896ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            updateRows();
3906ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            // Initialize listeners
3916ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            mDvrDataManager.addRecordedProgramListener(this);
3926ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            mDvrDataManager.addScheduledRecordingListener(this);
3936ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            mDvrDataManager.addSeriesRecordingListener(this);
3946ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            mDvrScheudleManager.addOnConflictStateChangeListener(mOnConflictStateChangeListener);
3956ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            startEntranceTransition();
3966ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            return true;
3976ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        }
3986ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        return false;
39965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
40065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
40165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private void handleRecordedProgramAdded(RecordedProgram recordedProgram,
40265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            boolean updateSeriesRecording) {
40365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        mRecentAdapter.add(recordedProgram);
40465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        String seriesId = recordedProgram.getSeriesId();
40565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        SeriesRecording seriesRecording = null;
40665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        if (seriesId != null) {
40765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            seriesRecording = mDvrDataManager.getSeriesRecording(seriesId);
40865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            RecordedProgram latestProgram = mSeriesId2LatestProgram.get(seriesId);
40965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            if (latestProgram == null || RecordedProgram.START_TIME_THEN_ID_COMPARATOR
41065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                    .compare(latestProgram, recordedProgram) < 0) {
41165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                mSeriesId2LatestProgram.put(seriesId, recordedProgram);
41265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                if (updateSeriesRecording && seriesRecording != null) {
41365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                    onSeriesRecordingChanged(seriesRecording);
41465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                }
41565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            }
41665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
41765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        if (seriesRecording == null) {
41865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            for (RecordedProgramAdapter adapter
41965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                    : getGenreAdapters(recordedProgram.getCanonicalGenres())) {
42065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                adapter.add(recordedProgram);
42165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            }
42265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
42365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
42465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
42565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private void handleRecordedProgramRemoved(RecordedProgram recordedProgram) {
42665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        mRecentAdapter.remove(recordedProgram);
42765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        String seriesId = recordedProgram.getSeriesId();
42865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        if (seriesId != null) {
42965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            SeriesRecording seriesRecording = mDvrDataManager.getSeriesRecording(seriesId);
43065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            RecordedProgram latestProgram =
43165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                    mSeriesId2LatestProgram.get(recordedProgram.getSeriesId());
43265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            if (latestProgram != null && latestProgram.getId() == recordedProgram.getId()) {
43365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                if (seriesRecording != null) {
43465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                    updateLatestRecordedProgram(seriesRecording);
43565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                    onSeriesRecordingChanged(seriesRecording);
4362e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko                }
43765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            }
43865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
43965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        for (RecordedProgramAdapter adapter
44065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                : getGenreAdapters(recordedProgram.getCanonicalGenres())) {
44165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            adapter.remove(recordedProgram);
44265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
44365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
44465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
44565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private void handleRecordedProgramChanged(RecordedProgram recordedProgram) {
44665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        mRecentAdapter.change(recordedProgram);
44765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        String seriesId = recordedProgram.getSeriesId();
44865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        SeriesRecording seriesRecording = null;
44965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        if (seriesId != null) {
45065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            seriesRecording = mDvrDataManager.getSeriesRecording(seriesId);
45165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            RecordedProgram latestProgram = mSeriesId2LatestProgram.get(seriesId);
45265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            if (latestProgram == null || RecordedProgram.START_TIME_THEN_ID_COMPARATOR
45365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                    .compare(latestProgram, recordedProgram) <= 0) {
45465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                mSeriesId2LatestProgram.put(seriesId, recordedProgram);
45565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                if (seriesRecording != null) {
45665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                    onSeriesRecordingChanged(seriesRecording);
4572e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko                }
45865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            } else if (latestProgram.getId() == recordedProgram.getId()) {
45965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                if (seriesRecording != null) {
46065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                    updateLatestRecordedProgram(seriesRecording);
46165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                    onSeriesRecordingChanged(seriesRecording);
4622e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko                }
463ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko            }
46465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
46565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        if (seriesRecording == null) {
46665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            updateGenreAdapters(getGenreAdapters(
46765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                    recordedProgram.getCanonicalGenres()), recordedProgram);
46865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        } else {
46965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            updateGenreAdapters(new ArrayList<>(), recordedProgram);
47065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
47165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
47265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
47365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private void handleSeriesRecordingsAdded(List<SeriesRecording> seriesRecordings) {
47465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        for (SeriesRecording seriesRecording : seriesRecordings) {
475d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            mSeriesAdapter.add(seriesRecording);
476d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            if (mSeriesId2LatestProgram.get(seriesRecording.getSeriesId()) != null) {
477d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                for (RecordedProgramAdapter adapter
478d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                        : getGenreAdapters(seriesRecording.getCanonicalGenreIds())) {
479d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                    adapter.add(seriesRecording);
48065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                }
48165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            }
48265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
48365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
48465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
48565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private void handleSeriesRecordingsRemoved(List<SeriesRecording> seriesRecordings) {
48665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        for (SeriesRecording seriesRecording : seriesRecordings) {
48765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            mSeriesAdapter.remove(seriesRecording);
48865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            for (RecordedProgramAdapter adapter
48965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                    : getGenreAdapters(seriesRecording.getCanonicalGenreIds())) {
49065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                adapter.remove(seriesRecording);
49165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            }
49265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
49365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
49465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
49565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private void handleSeriesRecordingsChanged(List<SeriesRecording> seriesRecordings) {
49665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        for (SeriesRecording seriesRecording : seriesRecordings) {
497d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            mSeriesAdapter.change(seriesRecording);
498d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            if (mSeriesId2LatestProgram.get(seriesRecording.getSeriesId()) != null) {
499d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                updateGenreAdapters(getGenreAdapters(
500d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                        seriesRecording.getCanonicalGenreIds()), seriesRecording);
501d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            } else {
502d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                // Remove series recording from all genre rows if it has no recorded program
503d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                updateGenreAdapters(new ArrayList<>(), seriesRecording);
50465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            }
50565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
50665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
50765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
50865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private List<RecordedProgramAdapter> getGenreAdapters(String[] genres) {
50965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        List<RecordedProgramAdapter> result = new ArrayList<>();
51065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        if (genres == null || genres.length == 0) {
51165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            result.add(mGenreAdapters[mGenreAdapters.length - 1]);
51265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        } else {
51365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            for (String genre : genres) {
51465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                int genreId = GenreItems.getId(genre);
51565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                if(genreId >= mGenreAdapters.length) {
51665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                    Log.d(TAG, "Wrong Genre ID: " + genreId);
51765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                } else {
51865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                    result.add(mGenreAdapters[genreId]);
51965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                }
52065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            }
52165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
52265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        return result;
52365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
52465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
52565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private List<RecordedProgramAdapter> getGenreAdapters(int[] genreIds) {
52665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        List<RecordedProgramAdapter> result = new ArrayList<>();
52765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        if (genreIds == null || genreIds.length == 0) {
52865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            result.add(mGenreAdapters[mGenreAdapters.length - 1]);
52965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        } else {
53065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            for (int genreId : genreIds) {
53165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                if(genreId >= mGenreAdapters.length) {
53265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                    Log.d(TAG, "Wrong Genre ID: " + genreId);
53365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                } else {
53465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                    result.add(mGenreAdapters[genreId]);
53565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                }
53665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            }
53765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
53865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        return result;
53965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
54065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
54165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private void updateGenreAdapters(List<RecordedProgramAdapter> adapters, Object r) {
54265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        for (RecordedProgramAdapter adapter : mGenreAdapters) {
54365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            if (adapters.contains(adapter)) {
54465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                adapter.change(r);
54565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            } else {
54665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                adapter.remove(r);
54765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            }
54865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
54965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
55065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
55165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private void postUpdateRows() {
55265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        mHandler.removeCallbacks(mUpdateRowsRunnable);
55365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        mHandler.post(mUpdateRowsRunnable);
55465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
55565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
55665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private void updateRows() {
55765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        int visibleRowsCount = 1;  // Schedule's Row will never be empty
55865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        if (mRecentAdapter.isEmpty()) {
55965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            mRowsAdapter.remove(mRecentRow);
56065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        } else {
56165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            if (mRowsAdapter.indexOf(mRecentRow) < 0) {
56265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                mRowsAdapter.add(0, mRecentRow);
56365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            }
56465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            visibleRowsCount++;
56565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
56665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        if (mSeriesAdapter.isEmpty()) {
56765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            mRowsAdapter.remove(mSeriesRow);
56865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        } else {
56965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            if (mRowsAdapter.indexOf(mSeriesRow) < 0) {
57065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                mRowsAdapter.add(visibleRowsCount, mSeriesRow);
57165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            }
57265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            visibleRowsCount++;
57365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
57465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        for (int i = 0; i < mGenreAdapters.length; i++) {
57565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            RecordedProgramAdapter adapter = mGenreAdapters[i];
57665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            if (adapter != null) {
57765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                if (adapter.isEmpty()) {
57865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                    mRowsAdapter.remove(mGenreRows[i]);
57965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                } else {
58065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                    if (mGenreRows[i] == null || mRowsAdapter.indexOf(mGenreRows[i]) < 0) {
58165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                        mGenreRows[i] = new ListRow(new HeaderItem(mGenreLabels.get(i)), adapter);
58265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                        mRowsAdapter.add(visibleRowsCount, mGenreRows[i]);
58365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                    }
58465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                    visibleRowsCount++;
58565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                }
58665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            }
58765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
58865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
58965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
59065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private boolean needToShowScheduledRecording(ScheduledRecording recording) {
59165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        int state = recording.getState();
592d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        return state == ScheduledRecording.STATE_RECORDING_IN_PROGRESS
593d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                || state == ScheduledRecording.STATE_RECORDING_NOT_STARTED;
59465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
59565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
59665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private void updateLatestRecordedProgram(SeriesRecording seriesRecording) {
59765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        RecordedProgram latestProgram = null;
59865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        for (RecordedProgram program :
59965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                mDvrDataManager.getRecordedPrograms(seriesRecording.getId())) {
600d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            if (latestProgram == null || RecordedProgram
601d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                    .START_TIME_THEN_ID_COMPARATOR.compare(latestProgram, program) < 0) {
60265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                latestProgram = program;
60365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            }
60465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
60565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        mSeriesId2LatestProgram.put(seriesRecording.getSeriesId(), latestProgram);
60665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
60765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
60865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private class ScheduleAdapter extends SortedArrayAdapter<Object> {
60965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        ScheduleAdapter(int maxItemCount) {
61065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            super(mPresenterSelector, SCHEDULE_COMPARATOR, maxItemCount);
61165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
61265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
61365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        @Override
61465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        public long getId(Object item) {
61565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            if (item instanceof ScheduledRecording) {
61665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                return ((ScheduledRecording) item).getId();
61765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            } else {
61865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                return -1;
61965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            }
62065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
62165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
62265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
623d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    private class SeriesAdapter extends SortedArrayAdapter<SeriesRecording> {
624d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        SeriesAdapter() {
625d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            super(mPresenterSelector, new Comparator<SeriesRecording>() {
626d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                @Override
627d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                public int compare(SeriesRecording lhs, SeriesRecording rhs) {
628d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                    if (lhs.isStopped() && !rhs.isStopped()) {
629d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                        return 1;
630d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                    } else if (!lhs.isStopped() && rhs.isStopped()) {
631d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                        return -1;
632d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                    }
633d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                    return SeriesRecording.PRIORITY_COMPARATOR.compare(lhs, rhs);
634d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                }
635d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            });
636d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        }
637d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko
638d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        @Override
639d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        public long getId(SeriesRecording item) {
640d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            return item.getId();
641d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        }
642d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    }
643d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko
64465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private class RecordedProgramAdapter extends SortedArrayAdapter<Object> {
64565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        RecordedProgramAdapter() {
64665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            this(Integer.MAX_VALUE);
64765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
64865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
64965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        RecordedProgramAdapter(int maxItemCount) {
65065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            super(mPresenterSelector, RECORDED_PROGRAM_COMPARATOR, maxItemCount);
65165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
65265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
65365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        @Override
65465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        public long getId(Object item) {
6556ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            // We takes the inverse number for the ID of recorded programs to make the ID stable.
65665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            if (item instanceof SeriesRecording) {
65765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                return ((SeriesRecording) item).getId();
65865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            } else if (item instanceof RecordedProgram) {
6596ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko                return -((RecordedProgram) item).getId() - 1;
66065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            } else {
66165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                return -1;
6622e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko            }
663ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        }
664ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    }
66565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko}