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
176ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkopackage com.android.tv.dvr.ui.browse;
1865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
1965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.content.res.Resources;
20d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalkoimport android.graphics.drawable.Drawable;
21d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalkoimport android.media.tv.TvInputManager;
2265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.os.Bundle;
2365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.support.v17.leanback.app.DetailsFragment;
2465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.support.v17.leanback.widget.Action;
2565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.support.v17.leanback.widget.ArrayObjectAdapter;
2665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.support.v17.leanback.widget.ClassPresenterSelector;
2765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.support.v17.leanback.widget.DetailsOverviewRow;
2865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.support.v17.leanback.widget.DetailsOverviewRowPresenter;
2965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.support.v17.leanback.widget.HeaderItem;
3065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.support.v17.leanback.widget.ListRow;
3165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.support.v17.leanback.widget.OnActionClickedListener;
3265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.support.v17.leanback.widget.PresenterSelector;
3365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.support.v17.leanback.widget.SparseArrayObjectAdapter;
3465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport android.text.TextUtils;
3565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
3665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport com.android.tv.R;
3765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport com.android.tv.TvApplication;
3865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport com.android.tv.data.BaseProgram;
3965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport com.android.tv.dvr.DvrDataManager;
40d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalkoimport com.android.tv.dvr.DvrWatchedPositionManager;
416ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport com.android.tv.dvr.data.RecordedProgram;
426ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport com.android.tv.dvr.data.SeriesRecording;
436ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport com.android.tv.dvr.ui.DvrUiHelper;
446ebde20b03db4c0d57f67acaac11832b610b966bNick Chalkoimport com.android.tv.dvr.ui.SortedArrayAdapter;
4565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
4665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport java.util.Collections;
4765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport java.util.Comparator;
4865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport java.util.List;
4965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
5065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko/**
5165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko * {@link DetailsFragment} for series recording in DVR.
5265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko */
5365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkopublic class SeriesRecordingDetailsFragment extends DvrDetailsFragment implements
5465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        DvrDataManager.SeriesRecordingListener, DvrDataManager.RecordedProgramListener {
55d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    private static final int ACTION_WATCH = 1;
56d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    private static final int ACTION_SERIES_SCHEDULES = 2;
57d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    private static final int ACTION_DELETE = 3;
5865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
59d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    private DvrWatchedPositionManager mDvrWatchedPositionManager;
6065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private DvrDataManager mDvrDataManager;
6165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
6265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private SeriesRecording mSeries;
6365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    // NOTICE: mRecordedPrograms should only be used in creating details fragments.
6465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    // After fragments are created, it should be cleared to save resources.
6565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private List<RecordedProgram> mRecordedPrograms;
66d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    private RecordedProgram mRecommendRecordedProgram;
6765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private int mSeasonRowCount;
6865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private SparseArrayObjectAdapter mActionsAdapter;
6965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private Action mDeleteAction;
7065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
71d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    private boolean mPaused;
72d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    private long mInitialPlaybackPositionMs;
73d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    private String mWatchLabel;
74d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    private String mResumeLabel;
75d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    private Drawable mWatchDrawable;
76d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    private RecordedProgramPresenter mRecordedProgramPresenter;
77d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko
7865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    @Override
7965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    public void onCreate(Bundle savedInstanceState) {
8065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        mDvrDataManager = TvApplication.getSingletons(getActivity()).getDvrDataManager();
81d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        mWatchLabel = getString(R.string.dvr_detail_watch);
82d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        mResumeLabel = getString(R.string.dvr_detail_series_resume);
83d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        mWatchDrawable = getResources().getDrawable(R.drawable.lb_ic_play, null);
846ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        mRecordedProgramPresenter = new RecordedProgramPresenter(getContext(), true, true);
8565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        super.onCreate(savedInstanceState);
86d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    }
87d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko
88d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    @Override
89d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    protected void onCreateInternal() {
90d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        mDvrWatchedPositionManager = TvApplication.getSingletons(getActivity())
91d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                .getDvrWatchedPositionManager();
926ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        setDetailsOverviewRow(DetailsContent.createFromSeriesRecording(getContext(), mSeries));
9365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        setupRecordedProgramsRow();
9465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        mDvrDataManager.addSeriesRecordingListener(this);
9565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        mDvrDataManager.addRecordedProgramListener(this);
9665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        mRecordedPrograms = null;
9765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
9865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
9965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    @Override
100d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    public void onResume() {
101d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        super.onResume();
102d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        if (mPaused) {
103d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            updateWatchAction();
104d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            mPaused = false;
105d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        }
106d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    }
107d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko
108d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    @Override
109d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    public void onPause() {
110d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        super.onPause();
111d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        mPaused = true;
112d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    }
113d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko
114d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    private void updateWatchAction() {
115d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        List<RecordedProgram> programs = mDvrDataManager.getRecordedPrograms(mSeries.getId());
116d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        Collections.sort(programs, RecordedProgram.EPISODE_COMPARATOR);
117d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        mRecommendRecordedProgram = getRecommendProgram(programs);
118d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        if (mRecommendRecordedProgram == null) {
119d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            mActionsAdapter.clear(ACTION_WATCH);
120d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        } else {
121d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            String episodeStatus;
122d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            if(mDvrWatchedPositionManager.getWatchedStatus(mRecommendRecordedProgram)
123d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                    == DvrWatchedPositionManager.DVR_WATCHED_STATUS_WATCHING) {
124d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                episodeStatus = mResumeLabel;
125d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                mInitialPlaybackPositionMs = mDvrWatchedPositionManager
126d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                        .getWatchedPosition(mRecommendRecordedProgram.getId());
127d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            } else {
128d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                episodeStatus = mWatchLabel;
129d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                mInitialPlaybackPositionMs = TvInputManager.TIME_SHIFT_INVALID_TIME;
130d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            }
131d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            String episodeDisplayNumber = mRecommendRecordedProgram.getEpisodeDisplayNumber(
132d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                    getContext());
133d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            mActionsAdapter.set(ACTION_WATCH, new Action(ACTION_WATCH,
134d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                    episodeStatus, episodeDisplayNumber, mWatchDrawable));
135d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        }
136d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    }
137d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko
138d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    @Override
13965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    protected boolean onLoadRecordingDetails(Bundle args) {
14065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        long recordId = args.getLong(DvrDetailsActivity.RECORDING_ID);
14165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        mSeries = TvApplication.getSingletons(getActivity()).getDvrDataManager()
14265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                .getSeriesRecording(recordId);
14365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        if (mSeries == null) {
14465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            return false;
14565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
14665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        mRecordedPrograms = mDvrDataManager.getRecordedPrograms(mSeries.getId());
14765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        Collections.sort(mRecordedPrograms, RecordedProgram.SEASON_REVERSED_EPISODE_COMPARATOR);
14865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        return true;
14965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
15065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
15165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    @Override
15265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    protected PresenterSelector onCreatePresenterSelector(
15365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            DetailsOverviewRowPresenter rowPresenter) {
15465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        ClassPresenterSelector presenterSelector = new ClassPresenterSelector();
15565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        presenterSelector.addClassPresenter(DetailsOverviewRow.class, rowPresenter);
1566ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko        presenterSelector.addClassPresenter(ListRow.class, new DvrListRowPresenter(getContext()));
15765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        return presenterSelector;
15865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
15965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
16065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    @Override
16165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    protected SparseArrayObjectAdapter onCreateActionsAdapter() {
16265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        mActionsAdapter = new SparseArrayObjectAdapter(new ActionPresenterSelector());
16365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        Resources res = getResources();
164d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        updateWatchAction();
16565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        mActionsAdapter.set(ACTION_SERIES_SCHEDULES, new Action(ACTION_SERIES_SCHEDULES,
16665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                getString(R.string.dvr_detail_view_schedule), null,
16765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                res.getDrawable(R.drawable.ic_schedule_32dp, null)));
16865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        mDeleteAction = new Action(ACTION_DELETE,
16965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                getString(R.string.dvr_detail_series_delete), null,
17065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                res.getDrawable(R.drawable.ic_delete_32dp, null));
17165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        if (!mRecordedPrograms.isEmpty()) {
17265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            mActionsAdapter.set(ACTION_DELETE, mDeleteAction);
17365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
17465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        return mActionsAdapter;
17565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
17665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
17765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private void setupRecordedProgramsRow() {
17865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        for (RecordedProgram program : mRecordedPrograms) {
17965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            addProgram(program);
18065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
18165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
18265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
18365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    @Override
18465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    public void onDestroy() {
18565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        super.onDestroy();
18665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        mDvrDataManager.removeSeriesRecordingListener(this);
18765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        mDvrDataManager.removeRecordedProgramListener(this);
188d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        if (mSeries != null) {
1896ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko            mDvrDataManager.checkAndRemoveEmptySeriesRecording(mSeries.getId());
19065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
191d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        mRecordedProgramPresenter.unbindAllViewHolders();
19265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
19365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
19465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    @Override
19565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    protected OnActionClickedListener onCreateOnActionClickedListener() {
19665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        return new OnActionClickedListener() {
19765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            @Override
19865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            public void onActionClicked(Action action) {
199d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                if (action.getId() == ACTION_WATCH) {
200d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                    startPlayback(mRecommendRecordedProgram, mInitialPlaybackPositionMs);
201d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                } else if (action.getId() == ACTION_SERIES_SCHEDULES) {
20265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                    DvrUiHelper.startSchedulesActivityForSeries(getContext(), mSeries);
20365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                } else if (action.getId() == ACTION_DELETE) {
20465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                    DvrUiHelper.startSeriesDeletionActivity(getContext(), mSeries.getId());
20565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                }
20665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            }
20765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        };
20865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
20965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
210d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    /**
211d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko     * The programs are sorted by season number and episode number.
212d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko     */
213d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    private RecordedProgram getRecommendProgram(List<RecordedProgram> programs) {
214d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        for (int i = programs.size() - 1 ; i >= 0 ; i--) {
215d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            RecordedProgram program = programs.get(i);
216d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            int watchedStatus = mDvrWatchedPositionManager.getWatchedStatus(program);
217d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            if (watchedStatus == DvrWatchedPositionManager.DVR_WATCHED_STATUS_NEW) {
218d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                continue;
219d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            }
220d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            if (watchedStatus == DvrWatchedPositionManager.DVR_WATCHED_STATUS_WATCHING) {
221d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                return program;
222d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            }
223d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            if (i == programs.size() - 1) {
224d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                return program;
225d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            } else {
226d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                return programs.get(i + 1);
227d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            }
228d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        }
229d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        return programs.isEmpty() ? null : programs.get(0);
230d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    }
231d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko
23265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    @Override
23365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    public void onSeriesRecordingAdded(SeriesRecording... seriesRecordings) { }
23465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
23565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    @Override
23665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    public void onSeriesRecordingChanged(SeriesRecording... seriesRecordings) {
23765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        for (SeriesRecording series : seriesRecordings) {
23865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            if (mSeries.getId() == series.getId()) {
23965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                mSeries = series;
24065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            }
24165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
24265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
24365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
24465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    @Override
245d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    public void onSeriesRecordingRemoved(SeriesRecording... seriesRecordings) {
246d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        for (SeriesRecording series : seriesRecordings) {
247d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            if (series.getId() == mSeries.getId()) {
248d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                getActivity().finish();
249d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                return;
250d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            }
251d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        }
252d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    }
25365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
25465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    @Override
255d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    public void onRecordedProgramsAdded(RecordedProgram... recordedPrograms) {
256d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        for (RecordedProgram recordedProgram : recordedPrograms) {
257d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            if (TextUtils.equals(recordedProgram.getSeriesId(), mSeries.getSeriesId())) {
258d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                addProgram(recordedProgram);
259d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                if (mActionsAdapter.lookup(ACTION_DELETE) == null) {
260d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                    mActionsAdapter.set(ACTION_DELETE, mDeleteAction);
261d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                }
26265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            }
26365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
26465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
26565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
26665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    @Override
267d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    public void onRecordedProgramsChanged(RecordedProgram... recordedPrograms) {
26865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        // Do nothing
26965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
27065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
27165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    @Override
272d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko    public void onRecordedProgramsRemoved(RecordedProgram... recordedPrograms) {
273d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        for (RecordedProgram recordedProgram : recordedPrograms) {
274d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko            if (TextUtils.equals(recordedProgram.getSeriesId(), mSeries.getSeriesId())) {
275d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                ListRow row = getSeasonRow(recordedProgram.getSeasonNumber(), false);
276d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                if (row != null) {
277d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                    SeasonRowAdapter adapter = (SeasonRowAdapter) row.getAdapter();
278d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                    adapter.remove(recordedProgram);
279d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                    if (adapter.isEmpty()) {
280d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                        getRowsAdapter().remove(row);
281d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                        if (getRowsAdapter().size() == 1) {
282d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                            // No season rows left. Only DetailsOverviewRow
283d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                            mActionsAdapter.clear(ACTION_DELETE);
284d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                        }
28565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                    }
28665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                }
287d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                if (recordedProgram.getId() == mRecommendRecordedProgram.getId()) {
288d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                    updateWatchAction();
289d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                }
29065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            }
29165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
29265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
29365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
29465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private void addProgram(RecordedProgram program) {
29565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        String programSeasonNumber =
29665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                TextUtils.isEmpty(program.getSeasonNumber()) ? "" : program.getSeasonNumber();
29765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        getOrCreateSeasonRowAdapter(programSeasonNumber).add(program);
29865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
29965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
30065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private SeasonRowAdapter getOrCreateSeasonRowAdapter(String seasonNumber) {
30165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        ListRow row = getSeasonRow(seasonNumber, true);
30265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        return (SeasonRowAdapter) row.getAdapter();
30365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
30465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
30565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private ListRow getSeasonRow(String seasonNumber, boolean createNewRow) {
30665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        seasonNumber = TextUtils.isEmpty(seasonNumber) ? "" : seasonNumber;
30765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        ArrayObjectAdapter rowsAdaptor = getRowsAdapter();
30865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        for (int i = rowsAdaptor.size() - 1; i >= 0; i--) {
30965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            Object row = rowsAdaptor.get(i);
31065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            if (row instanceof ListRow) {
311d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko                int compareResult = BaseProgram.numberCompare(seasonNumber,
31265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                        ((SeasonRowAdapter) ((ListRow) row).getAdapter()).mSeasonNumber);
31365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                if (compareResult == 0) {
31465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                    return (ListRow) row;
31565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                } else if (compareResult < 0) {
31665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                    return createNewRow ? createNewSeasonRow(seasonNumber, i + 1) : null;
31765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                }
31865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            }
31965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
32065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        return createNewRow ? createNewSeasonRow(seasonNumber, rowsAdaptor.size()) : null;
32165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
32265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
32365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private ListRow createNewSeasonRow(String seasonNumber, int position) {
32465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        String seasonTitle = seasonNumber.isEmpty() ? mSeries.getTitle()
32565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                : getString(R.string.dvr_detail_series_season_title, seasonNumber);
32665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        HeaderItem header = new HeaderItem(mSeasonRowCount++, seasonTitle);
32765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        ClassPresenterSelector selector = new ClassPresenterSelector();
328d41f0075a7d2ea826204e81fcec57d0aa57171a9Nick Chalko        selector.addClassPresenter(RecordedProgram.class, mRecordedProgramPresenter);
32965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        ListRow row = new ListRow(header, new SeasonRowAdapter(selector,
33065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                new Comparator<RecordedProgram>() {
33165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                    @Override
33265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                    public int compare(RecordedProgram lhs, RecordedProgram rhs) {
33365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                        return BaseProgram.EPISODE_COMPARATOR.compare(lhs, rhs);
33465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                    }
33565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                }, seasonNumber));
33665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        getRowsAdapter().add(position, row);
33765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        return row;
33865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
33965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
34065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    private class SeasonRowAdapter extends SortedArrayAdapter<RecordedProgram> {
34165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        private String mSeasonNumber;
34265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
34365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        SeasonRowAdapter(PresenterSelector selector, Comparator<RecordedProgram> comparator,
34465fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko                String seasonNumber) {
34565fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            super(selector, comparator);
34665fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            mSeasonNumber = seasonNumber;
34765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
34865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko
34965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        @Override
35065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        public long getId(RecordedProgram program) {
35165fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko            return program.getId();
35265fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko        }
35365fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko    }
3546ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko}