/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.tv.guide;

import android.support.annotation.MainThread;
import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting;
import android.util.ArraySet;
import android.util.Log;

import com.android.tv.data.ChannelDataManager;
import com.android.tv.data.GenreItems;
import com.android.tv.data.ProgramDataManager;
import com.android.tv.data.ProgramImpl;
import com.android.tv.data.api.Channel;
import com.android.tv.data.api.Program;
import com.android.tv.dvr.DvrDataManager;
import com.android.tv.dvr.DvrScheduleManager;
import com.android.tv.dvr.DvrScheduleManager.OnConflictStateChangeListener;
import com.android.tv.dvr.data.ScheduledRecording;
import com.android.tv.util.TvInputManagerHelper;
import com.android.tv.util.Utils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/** Manages the channels and programs for the program guide. */
@MainThread
public class ProgramManager {
    private static final String TAG = "ProgramManager";
    private static final boolean DEBUG = false;

    /**
     * If the first entry's visible duration is shorter than this value, we clip the entry out.
     * Note: If this value is larger than 1 min, it could cause mismatches between the entry's
     * position and detailed view's time range.
     */
    static final long FIRST_ENTRY_MIN_DURATION = TimeUnit.MINUTES.toMillis(1);

    private static final long INVALID_ID = -1;

    private final TvInputManagerHelper mTvInputManagerHelper;
    private final ChannelDataManager mChannelDataManager;
    private final ProgramDataManager mProgramDataManager;
    private final DvrDataManager mDvrDataManager; // Only set if DVR is enabled
    private final DvrScheduleManager mDvrScheduleManager;

    private long mStartUtcMillis;
    private long mEndUtcMillis;
    private long mFromUtcMillis;
    private long mToUtcMillis;

    private List<Channel> mChannels = new ArrayList<>();
    private final Map<Long, List<TableEntry>> mChannelIdEntriesMap = new HashMap<>();
    private final List<List<Channel>> mGenreChannelList = new ArrayList<>();
    private final List<Integer> mFilteredGenreIds = new ArrayList<>();

    // Position of selected genre to filter channel list.
    private int mSelectedGenreId = GenreItems.ID_ALL_CHANNELS;
    // Channel list after applying genre filter.
    // Should be matched with mSelectedGenreId always.
    private List<Channel> mFilteredChannels = mChannels;
    private boolean mChannelDataLoaded;

    private final Set<Listener> mListeners = new ArraySet<>();
    private final Set<TableEntriesUpdatedListener> mTableEntriesUpdatedListeners = new ArraySet<>();

    private final Set<TableEntryChangedListener> mTableEntryChangedListeners = new ArraySet<>();

    private final DvrDataManager.OnDvrScheduleLoadFinishedListener mDvrLoadedListener =
            new DvrDataManager.OnDvrScheduleLoadFinishedListener() {
                @Override
                public void onDvrScheduleLoadFinished() {
                    if (mChannelDataLoaded) {
                        for (ScheduledRecording r : mDvrDataManager.getAllScheduledRecordings()) {
                            mScheduledRecordingListener.onScheduledRecordingAdded(r);
                        }
                    }
                    mDvrDataManager.removeDvrScheduleLoadFinishedListener(this);
                }
            };

    private final ChannelDataManager.Listener mChannelDataManagerListener =
            new ChannelDataManager.Listener() {
                @Override
                public void onLoadFinished() {
                    mChannelDataLoaded = true;
                    updateChannels(false);
                }

                @Override
                public void onChannelListUpdated() {
                    updateChannels(false);
                }

                @Override
                public void onChannelBrowsableChanged() {
                    updateChannels(false);
                }
            };

    private final ProgramDataManager.Callback mProgramDataManagerCallback =
            new ProgramDataManager.Callback() {
                @Override
                public void onProgramUpdated() {
                    updateTableEntries(true);
                }

                @Override
                public void onChannelUpdated() {
                    updateTableEntriesWithoutNotification(false);
                    notifyTableEntriesUpdated();
                }
            };

    private final DvrDataManager.ScheduledRecordingListener mScheduledRecordingListener =
            new DvrDataManager.ScheduledRecordingListener() {
                @Override
                public void onScheduledRecordingAdded(ScheduledRecording... scheduledRecordings) {
                    for (ScheduledRecording schedule : scheduledRecordings) {
                        TableEntry oldEntry = getTableEntry(schedule);
                        if (oldEntry != null) {
                            TableEntry newEntry =
                                    new TableEntry(
                                            oldEntry.channelId,
                                            oldEntry.program,
                                            schedule,
                                            oldEntry.entryStartUtcMillis,
                                            oldEntry.entryEndUtcMillis,
                                            oldEntry.isBlocked());
                            updateEntry(oldEntry, newEntry);
                        }
                    }
                }

                @Override
                public void onScheduledRecordingRemoved(ScheduledRecording... scheduledRecordings) {
                    for (ScheduledRecording schedule : scheduledRecordings) {
                        TableEntry oldEntry = getTableEntry(schedule);
                        if (oldEntry != null) {
                            TableEntry newEntry =
                                    new TableEntry(
                                            oldEntry.channelId,
                                            oldEntry.program,
                                            null,
                                            oldEntry.entryStartUtcMillis,
                                            oldEntry.entryEndUtcMillis,
                                            oldEntry.isBlocked());
                            updateEntry(oldEntry, newEntry);
                        }
                    }
                }

                @Override
                public void onScheduledRecordingStatusChanged(
                        ScheduledRecording... scheduledRecordings) {
                    for (ScheduledRecording schedule : scheduledRecordings) {
                        TableEntry oldEntry = getTableEntry(schedule);
                        if (oldEntry != null) {
                            TableEntry newEntry =
                                    new TableEntry(
                                            oldEntry.channelId,
                                            oldEntry.program,
                                            schedule,
                                            oldEntry.entryStartUtcMillis,
                                            oldEntry.entryEndUtcMillis,
                                            oldEntry.isBlocked());
                            updateEntry(oldEntry, newEntry);
                        }
                    }
                }
            };

    private final OnConflictStateChangeListener mOnConflictStateChangeListener =
            new OnConflictStateChangeListener() {
                @Override
                public void onConflictStateChange(
                        boolean conflict, ScheduledRecording... schedules) {
                    for (ScheduledRecording schedule : schedules) {
                        TableEntry entry = getTableEntry(schedule);
                        if (entry != null) {
                            notifyTableEntryUpdated(entry);
                        }
                    }
                }
            };

    public ProgramManager(
            TvInputManagerHelper tvInputManagerHelper,
            ChannelDataManager channelDataManager,
            ProgramDataManager programDataManager,
            @Nullable DvrDataManager dvrDataManager,
            @Nullable DvrScheduleManager dvrScheduleManager) {
        mTvInputManagerHelper = tvInputManagerHelper;
        mChannelDataManager = channelDataManager;
        mProgramDataManager = programDataManager;
        mDvrDataManager = dvrDataManager;
        mDvrScheduleManager = dvrScheduleManager;
    }

    void programGuideVisibilityChanged(boolean visible) {
        mProgramDataManager.setPauseProgramUpdate(visible);
        if (visible) {
            mChannelDataManager.addListener(mChannelDataManagerListener);
            mProgramDataManager.addCallback(mProgramDataManagerCallback);
            if (mDvrDataManager != null) {
                if (!mDvrDataManager.isDvrScheduleLoadFinished()) {
                    mDvrDataManager.addDvrScheduleLoadFinishedListener(mDvrLoadedListener);
                }
                mDvrDataManager.addScheduledRecordingListener(mScheduledRecordingListener);
            }
            if (mDvrScheduleManager != null) {
                mDvrScheduleManager.addOnConflictStateChangeListener(
                        mOnConflictStateChangeListener);
            }
        } else {
            mChannelDataManager.removeListener(mChannelDataManagerListener);
            mProgramDataManager.removeCallback(mProgramDataManagerCallback);
            if (mDvrDataManager != null) {
                mDvrDataManager.removeDvrScheduleLoadFinishedListener(mDvrLoadedListener);
                mDvrDataManager.removeScheduledRecordingListener(mScheduledRecordingListener);
            }
            if (mDvrScheduleManager != null) {
                mDvrScheduleManager.removeOnConflictStateChangeListener(
                        mOnConflictStateChangeListener);
            }
        }
    }

    /** Adds a {@link Listener}. */
    void addListener(Listener listener) {
        mListeners.add(listener);
    }

    /** Registers a listener to be invoked when table entries are updated. */
    void addTableEntriesUpdatedListener(TableEntriesUpdatedListener listener) {
        mTableEntriesUpdatedListeners.add(listener);
    }

    /** Registers a listener to be invoked when a table entry is changed. */
    void addTableEntryChangedListener(TableEntryChangedListener listener) {
        mTableEntryChangedListeners.add(listener);
    }

    /** Removes a {@link Listener}. */
    void removeListener(Listener listener) {
        mListeners.remove(listener);
    }

    /** Removes a previously installed table entries update listener. */
    void removeTableEntriesUpdatedListener(TableEntriesUpdatedListener listener) {
        mTableEntriesUpdatedListeners.remove(listener);
    }

    /** Removes a previously installed table entry changed listener. */
    void removeTableEntryChangedListener(TableEntryChangedListener listener) {
        mTableEntryChangedListeners.remove(listener);
    }

    /**
     * Resets channel list with given genre. Caller should call {@link #buildGenreFilters()} prior
     * to call this API to make This notifies channel updates to listeners.
     */
    void resetChannelListWithGenre(int genreId) {
        if (genreId == mSelectedGenreId) {
            return;
        }
        mFilteredChannels = mGenreChannelList.get(genreId);
        mSelectedGenreId = genreId;
        if (DEBUG) {
            Log.d(
                    TAG,
                    "resetChannelListWithGenre: "
                            + GenreItems.getCanonicalGenre(genreId)
                            + " has "
                            + mFilteredChannels.size()
                            + " channels out of "
                            + mChannels.size());
        }
        if (mGenreChannelList.get(mSelectedGenreId) == null) {
            throw new IllegalStateException("Genre filter isn't ready.");
        }
        notifyChannelsUpdated();
    }

    /** Update the initial time range to manage. It updates program entries and genre as well. */
    void updateInitialTimeRange(long startUtcMillis, long endUtcMillis) {
        mStartUtcMillis = startUtcMillis;
        if (endUtcMillis > mEndUtcMillis) {
            mEndUtcMillis = endUtcMillis;
        }

        mProgramDataManager.setPrefetchTimeRange(mStartUtcMillis);
        updateChannels(true);
        setTimeRange(startUtcMillis, endUtcMillis);
    }

    /** Shifts the time range by the given time. Also makes ProgramGuide scroll the views. */
    void shiftTime(long timeMillisToScroll) {
        long fromUtcMillis = mFromUtcMillis + timeMillisToScroll;
        long toUtcMillis = mToUtcMillis + timeMillisToScroll;
        if (fromUtcMillis < mStartUtcMillis) {
            toUtcMillis += mStartUtcMillis - fromUtcMillis;
            fromUtcMillis = mStartUtcMillis;
        }
        if (toUtcMillis > mEndUtcMillis) {
            fromUtcMillis -= toUtcMillis - mEndUtcMillis;
            toUtcMillis = mEndUtcMillis;
        }
        setTimeRange(fromUtcMillis, toUtcMillis);
    }

    /** Returned the scrolled(shifted) time in milliseconds. */
    long getShiftedTime() {
        return mFromUtcMillis - mStartUtcMillis;
    }

    /** Returns the start time set by {@link #updateInitialTimeRange}. */
    long getStartTime() {
        return mStartUtcMillis;
    }

    /** Returns the program index of the program with {@code entryId} or -1 if not found. */
    int getProgramIdIndex(long channelId, long entryId) {
        List<TableEntry> entries = mChannelIdEntriesMap.get(channelId);
        if (entries != null) {
            for (int i = 0; i < entries.size(); i++) {
                if (entries.get(i).getId() == entryId) {
                    return i;
                }
            }
        }
        return -1;
    }

    /** Returns the program index of the program at {@code time} or -1 if not found. */
    int getProgramIndexAtTime(long channelId, long time) {
        List<TableEntry> entries = mChannelIdEntriesMap.get(channelId);
        if (entries != null) {
            for (int i = 0; i < entries.size(); ++i) {
                TableEntry entry = entries.get(i);
                if (entry.entryStartUtcMillis <= time && time < entry.entryEndUtcMillis) {
                    return i;
                }
            }
        }
        return -1;
    }

    /** Returns the start time of currently managed time range, in UTC millisecond. */
    long getFromUtcMillis() {
        return mFromUtcMillis;
    }

    /** Returns the end time of currently managed time range, in UTC millisecond. */
    long getToUtcMillis() {
        return mToUtcMillis;
    }

    /** Returns the number of the currently managed channels. */
    int getChannelCount() {
        return mFilteredChannels.size();
    }

    /**
     * Returns a {@link Channel} at a given {@code channelIndex} of the currently managed channels.
     * Returns {@code null} if such a channel is not found.
     */
    Channel getChannel(int channelIndex) {
        if (channelIndex < 0 || channelIndex >= getChannelCount()) {
            return null;
        }
        return mFilteredChannels.get(channelIndex);
    }

    /**
     * Returns the index of provided {@link Channel} within the currently managed channels. Returns
     * -1 if such a channel is not found.
     */
    int getChannelIndex(Channel channel) {
        return mFilteredChannels.indexOf(channel);
    }

    /**
     * Returns the index of channel with {@code channelId} within the currently managed channels.
     * Returns -1 if such a channel is not found.
     */
    int getChannelIndex(long channelId) {
        return getChannelIndex(mChannelDataManager.getChannel(channelId));
    }

    /**
     * Returns the number of "entries", which lies within the currently managed time range, for a
     * given {@code channelId}.
     */
    int getTableEntryCount(long channelId) {
        return mChannelIdEntriesMap.isEmpty() ? 0 : mChannelIdEntriesMap.get(channelId).size();
    }

    /**
     * Returns an entry as {@link ProgramImpl} for a given {@code channelId} and {@code index} of
     * entries within the currently managed time range. Returned {@link ProgramImpl} can be a dummy
     * one (e.g., whose channelId is INVALID_ID), when it corresponds to a gap between programs.
     */
    TableEntry getTableEntry(long channelId, int index) {
        mProgramDataManager.prefetchChannel(channelId, index);
        return mChannelIdEntriesMap.get(channelId).get(index);
    }

    /** Returns list genre ID's which has a channel. */
    List<Integer> getFilteredGenreIds() {
        return mFilteredGenreIds;
    }

    int getSelectedGenreId() {
        return mSelectedGenreId;
    }

    // Note that This can be happens only if program guide isn't shown
    // because an user has to select channels as browsable through UI.
    private void updateChannels(boolean clearPreviousTableEntries) {
        if (DEBUG) Log.d(TAG, "updateChannels");
        mChannels = mChannelDataManager.getBrowsableChannelList();
        mSelectedGenreId = GenreItems.ID_ALL_CHANNELS;
        mFilteredChannels = mChannels;
        updateTableEntriesWithoutNotification(clearPreviousTableEntries);
        // Channel update notification should be called after updating table entries, so that
        // the listener can get the entries.
        notifyChannelsUpdated();
        notifyTableEntriesUpdated();
        buildGenreFilters();
    }

    /** Sets the channel list for testing */
    void setChannels(List<Channel> channels) {
        mChannels = new ArrayList<>(channels);
        mSelectedGenreId = GenreItems.ID_ALL_CHANNELS;
        mFilteredChannels = mChannels;
        buildGenreFilters();
    }

    private void updateTableEntries(boolean clear) {
        updateTableEntriesWithoutNotification(clear);
        notifyTableEntriesUpdated();
        buildGenreFilters();
    }

    /** Updates the table entries without notifying the change. */
    private void updateTableEntriesWithoutNotification(boolean clear) {
        if (clear) {
            mChannelIdEntriesMap.clear();
        }
        boolean parentalControlsEnabled =
                mTvInputManagerHelper.getParentalControlSettings().isParentalControlsEnabled();
        for (Channel channel : mChannels) {
            long channelId = channel.getId();
            // Inline the updating of the mChannelIdEntriesMap here so we can only call
            // getParentalControlSettings once.
            List<TableEntry> entries = createProgramEntries(channelId, parentalControlsEnabled);
            mChannelIdEntriesMap.put(channelId, entries);

            int size = entries.size();
            if (DEBUG) {
                Log.d(
                        TAG,
                        "Programs are loaded for channel "
                                + channel.getId()
                                + ", loaded size = "
                                + size);
            }
            if (size == 0) {
                continue;
            }
            TableEntry lastEntry = entries.get(size - 1);
            if (mEndUtcMillis < lastEntry.entryEndUtcMillis
                    && lastEntry.entryEndUtcMillis != Long.MAX_VALUE) {
                mEndUtcMillis = lastEntry.entryEndUtcMillis;
            }
        }
        if (mEndUtcMillis > mStartUtcMillis) {
            for (Channel channel : mChannels) {
                long channelId = channel.getId();
                List<TableEntry> entries = mChannelIdEntriesMap.get(channelId);
                if (entries.isEmpty()) {
                    entries.add(new TableEntry(channelId, mStartUtcMillis, mEndUtcMillis));
                } else {
                    TableEntry lastEntry = entries.get(entries.size() - 1);
                    if (mEndUtcMillis > lastEntry.entryEndUtcMillis) {
                        entries.add(
                                new TableEntry(
                                        channelId, lastEntry.entryEndUtcMillis, mEndUtcMillis));
                    } else if (lastEntry.entryEndUtcMillis == Long.MAX_VALUE) {
                        entries.remove(entries.size() - 1);
                        entries.add(
                                new TableEntry(
                                        lastEntry.channelId,
                                        lastEntry.program,
                                        lastEntry.scheduledRecording,
                                        lastEntry.entryStartUtcMillis,
                                        mEndUtcMillis,
                                        lastEntry.mIsBlocked));
                    }
                }
            }
        }
    }

    /**
     * Build genre filters based on the current programs. This categories channels by its current
     * program's canonical genres and subsequent @{link resetChannelListWithGenre(int)} calls will
     * reset channel list with built channel list. This is expected to be called whenever program
     * guide is shown.
     */
    private void buildGenreFilters() {
        if (DEBUG) Log.d(TAG, "buildGenreFilters");

        mGenreChannelList.clear();
        for (int i = 0; i < GenreItems.getGenreCount(); i++) {
            mGenreChannelList.add(new ArrayList<>());
        }
        for (Channel channel : mChannels) {
            Program currentProgram = mProgramDataManager.getCurrentProgram(channel.getId());
            if (currentProgram != null && currentProgram.getCanonicalGenres() != null) {
                for (String genre : currentProgram.getCanonicalGenres()) {
                    mGenreChannelList.get(GenreItems.getId(genre)).add(channel);
                }
            }
        }
        mGenreChannelList.set(GenreItems.ID_ALL_CHANNELS, mChannels);
        mFilteredGenreIds.clear();
        mFilteredGenreIds.add(0);
        for (int i = 1; i < GenreItems.getGenreCount(); i++) {
            if (mGenreChannelList.get(i).size() > 0) {
                mFilteredGenreIds.add(i);
            }
        }
        mSelectedGenreId = GenreItems.ID_ALL_CHANNELS;
        mFilteredChannels = mChannels;
        notifyGenresUpdated();
    }

    @Nullable
    private TableEntry getTableEntry(ScheduledRecording scheduledRecording) {
        return getTableEntry(scheduledRecording.getChannelId(), scheduledRecording.getProgramId());
    }

    @Nullable
    private TableEntry getTableEntry(long channelId, long entryId) {
        if (mChannelIdEntriesMap.isEmpty()) {
            return null;
        }
        List<TableEntry> entries = mChannelIdEntriesMap.get(channelId);
        if (entries != null) {
            for (TableEntry entry : entries) {
                if (entry.getId() == entryId) {
                    return entry;
                }
            }
        }
        return null;
    }

    private void updateEntry(TableEntry old, TableEntry newEntry) {
        List<TableEntry> entries = mChannelIdEntriesMap.get(old.channelId);
        int index = entries.indexOf(old);
        entries.set(index, newEntry);
        notifyTableEntryUpdated(newEntry);
    }

    private void setTimeRange(long fromUtcMillis, long toUtcMillis) {
        if (DEBUG) {
            Log.d(
                    TAG,
                    "setTimeRange. {FromTime="
                            + Utils.toTimeString(fromUtcMillis)
                            + ", ToTime="
                            + Utils.toTimeString(toUtcMillis)
                            + "}");
        }
        if (mFromUtcMillis != fromUtcMillis || mToUtcMillis != toUtcMillis) {
            mFromUtcMillis = fromUtcMillis;
            mToUtcMillis = toUtcMillis;
            notifyTimeRangeUpdated();
        }
    }

    private List<TableEntry> createProgramEntries(long channelId, boolean parentalControlsEnabled) {
        List<TableEntry> entries = new ArrayList<>();
        boolean channelLocked =
                parentalControlsEnabled && mChannelDataManager.getChannel(channelId).isLocked();
        if (channelLocked) {
            entries.add(new TableEntry(channelId, mStartUtcMillis, Long.MAX_VALUE, true));
        } else {
            long lastProgramEndTime = mStartUtcMillis;
            List<Program> programs = mProgramDataManager.getPrograms(channelId, mStartUtcMillis);
            for (Program program : programs) {
                if (program.getChannelId() == INVALID_ID) {
                    // Dummy program.
                    continue;
                }
                long programStartTime = Math.max(program.getStartTimeUtcMillis(), mStartUtcMillis);
                long programEndTime = program.getEndTimeUtcMillis();
                if (programStartTime > lastProgramEndTime) {
                    // Gap since the last program.
                    entries.add(new TableEntry(channelId, lastProgramEndTime, programStartTime));
                    lastProgramEndTime = programStartTime;
                }
                if (programEndTime > lastProgramEndTime) {
                    ScheduledRecording scheduledRecording =
                            mDvrDataManager == null
                                    ? null
                                    : mDvrDataManager.getScheduledRecordingForProgramId(
                                            program.getId());
                    entries.add(
                            new TableEntry(
                                    channelId,
                                    program,
                                    scheduledRecording,
                                    lastProgramEndTime,
                                    programEndTime,
                                    false));
                    lastProgramEndTime = programEndTime;
                }
            }
        }

        if (entries.size() > 1) {
            TableEntry secondEntry = entries.get(1);
            if (secondEntry.entryStartUtcMillis < mStartUtcMillis + FIRST_ENTRY_MIN_DURATION) {
                // If the first entry's width doesn't have enough width, it is not good to show
                // the first entry from UI perspective. So we clip it out.
                entries.remove(0);
                entries.set(
                        0,
                        new TableEntry(
                                secondEntry.channelId,
                                secondEntry.program,
                                secondEntry.scheduledRecording,
                                mStartUtcMillis,
                                secondEntry.entryEndUtcMillis,
                                secondEntry.mIsBlocked));
            }
        }
        return entries;
    }

    private void notifyGenresUpdated() {
        for (Listener listener : mListeners) {
            listener.onGenresUpdated();
        }
    }

    private void notifyChannelsUpdated() {
        for (Listener listener : mListeners) {
            listener.onChannelsUpdated();
        }
    }

    private void notifyTimeRangeUpdated() {
        for (Listener listener : mListeners) {
            listener.onTimeRangeUpdated();
        }
    }

    private void notifyTableEntriesUpdated() {
        for (TableEntriesUpdatedListener listener : mTableEntriesUpdatedListeners) {
            listener.onTableEntriesUpdated();
        }
    }

    private void notifyTableEntryUpdated(TableEntry entry) {
        for (TableEntryChangedListener listener : mTableEntryChangedListeners) {
            listener.onTableEntryChanged(entry);
        }
    }

    /**
     * Entry for program guide table. An "entry" can be either an actual program or a gap between
     * programs. This is needed for {@link ProgramListAdapter} because {@link
     * androidx.leanback.widget.HorizontalGridView} ignores margins between items.
     */
    static class TableEntry {
        /** Channel ID which this entry is included. */
        final long channelId;

        /** Program corresponding to the entry. {@code null} means that this entry is a gap. */
        final Program program;

        final ScheduledRecording scheduledRecording;

        /** Start time of entry in UTC milliseconds. */
        final long entryStartUtcMillis;

        /** End time of entry in UTC milliseconds */
        final long entryEndUtcMillis;

        private final boolean mIsBlocked;

        private TableEntry(long channelId, long startUtcMillis, long endUtcMillis) {
            this(channelId, null, startUtcMillis, endUtcMillis, false);
        }

        private TableEntry(
                long channelId, long startUtcMillis, long endUtcMillis, boolean blocked) {
            this(channelId, null, null, startUtcMillis, endUtcMillis, blocked);
        }

        private TableEntry(
                long channelId,
                ProgramImpl program,
                long entryStartUtcMillis,
                long entryEndUtcMillis,
                boolean isBlocked) {
            this(channelId, program, null, entryStartUtcMillis, entryEndUtcMillis, isBlocked);
        }

        private TableEntry(
                long channelId,
                Program program,
                ScheduledRecording scheduledRecording,
                long entryStartUtcMillis,
                long entryEndUtcMillis,
                boolean isBlocked) {
            this.channelId = channelId;
            this.program = program;
            this.scheduledRecording = scheduledRecording;
            this.entryStartUtcMillis = entryStartUtcMillis;
            this.entryEndUtcMillis = entryEndUtcMillis;
            mIsBlocked = isBlocked;
        }

        /** A stable id useful for {@link androidx.recyclerview.widget.RecyclerView.Adapter}. */
        long getId() {
            // using a negative entryEndUtcMillis keeps it from conflicting with program Id
            return program != null ? program.getId() : -entryEndUtcMillis;
        }

        /** Returns true if this is a gap. */
        boolean isGap() {
            return !Program.isProgramValid(program);
        }

        /** Returns true if this channel is blocked. */
        boolean isBlocked() {
            return mIsBlocked;
        }

        /** Returns true if this program is on the air. */
        boolean isCurrentProgram() {
            long current = System.currentTimeMillis();
            return entryStartUtcMillis <= current && entryEndUtcMillis > current;
        }

        /** Returns if this program has the genre. */
        boolean hasGenre(int genreId) {
            return !isGap() && program.hasGenre(genreId);
        }

        /** Returns the width of table entry, in pixels. */
        int getWidth() {
            return GuideUtils.convertMillisToPixel(entryStartUtcMillis, entryEndUtcMillis);
        }

        @Override
        public String toString() {
            return "TableEntry{"
                    + "hashCode="
                    + hashCode()
                    + ", channelId="
                    + channelId
                    + ", program="
                    + program
                    + ", startTime="
                    + Utils.toTimeString(entryStartUtcMillis)
                    + ", endTimeTime="
                    + Utils.toTimeString(entryEndUtcMillis)
                    + "}";
        }
    }

    @VisibleForTesting
    public static TableEntry createTableEntryForTest(
            long channelId,
            Program program,
            ScheduledRecording scheduledRecording,
            long entryStartUtcMillis,
            long entryEndUtcMillis,
            boolean isBlocked) {
        return new TableEntry(
                channelId,
                program,
                scheduledRecording,
                entryStartUtcMillis,
                entryEndUtcMillis,
                isBlocked);
    }

    interface Listener {
        void onGenresUpdated();

        void onChannelsUpdated();

        void onTimeRangeUpdated();
    }

    interface TableEntriesUpdatedListener {
        void onTableEntriesUpdated();
    }

    interface TableEntryChangedListener {
        void onTableEntryChanged(TableEntry entry);
    }

    static class ListenerAdapter implements Listener {
        @Override
        public void onGenresUpdated() {}

        @Override
        public void onChannelsUpdated() {}

        @Override
        public void onTimeRangeUpdated() {}
    }
}
