/*
* Copyright (C) 2013 Simon Vig Therkildsen
*
* 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 net.simonvt.cathode.scheduler;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import javax.inject.Inject;
import net.simonvt.cathode.api.enumeration.ItemType;
import net.simonvt.cathode.api.util.TimeUtils;
import net.simonvt.cathode.jobqueue.Job;
import net.simonvt.cathode.provider.DatabaseContract.EpisodeColumns;
import net.simonvt.cathode.provider.DatabaseContract.ShowColumns;
import net.simonvt.cathode.provider.EpisodeDatabaseHelper;
import net.simonvt.cathode.provider.ProviderSchematic.Episodes;
import net.simonvt.cathode.provider.ProviderSchematic.Shows;
import net.simonvt.cathode.provider.ShowDatabaseHelper;
import net.simonvt.cathode.remote.action.shows.CheckInEpisode;
import net.simonvt.cathode.remote.action.shows.CollectEpisode;
import net.simonvt.cathode.remote.action.shows.RateEpisode;
import net.simonvt.cathode.remote.action.shows.WatchedEpisode;
import net.simonvt.cathode.remote.action.shows.WatchlistEpisode;
import net.simonvt.cathode.remote.sync.SyncWatching;
import net.simonvt.cathode.remote.sync.comments.SyncComments;
import net.simonvt.cathode.remote.sync.shows.SyncSeason;
import net.simonvt.cathode.tmdb.api.show.SyncEpisodeImages;
import net.simonvt.cathode.util.DateUtils;
import net.simonvt.schematic.Cursors;
public class EpisodeTaskScheduler extends BaseTaskScheduler {
@Inject ShowDatabaseHelper showHelper;
@Inject EpisodeDatabaseHelper episodeHelper;
public EpisodeTaskScheduler(Context context) {
super(context);
}
public void sync(final long episodeId, final Job.OnDoneListener onDoneListener) {
execute(new Runnable() {
@Override public void run() {
final long showId = episodeHelper.getShowId(episodeId);
final int showTmdbId = showHelper.getTmdbId(showId);
final long traktId = showHelper.getTraktId(showId);
final int season = episodeHelper.getSeason(episodeId);
final int episode = episodeHelper.getNumber(episodeId);
queue(new SyncSeason(traktId, season));
queue(new SyncEpisodeImages(showTmdbId, season, episode));
Job syncComments = new SyncComments(ItemType.EPISODE, traktId, season, episode);
syncComments.registerOnDoneListener(onDoneListener);
queue(syncComments);
ContentValues values = new ContentValues();
values.put(EpisodeColumns.LAST_COMMENT_SYNC, System.currentTimeMillis());
context.getContentResolver().update(Episodes.withId(episodeId), values, null, null);
}
});
}
/**
* Add episodes watched outside of trakt to user library.
*
* @param episodeId The database id of the episode.
* @param watched Whether the episode has been watched.
*/
public void setWatched(final long episodeId, final boolean watched) {
execute(new Runnable() {
@Override public void run() {
String watchedAt = null;
long watchedAtMillis = 0L;
if (watched) {
watchedAt = TimeUtils.getIsoTime();
watchedAtMillis = TimeUtils.getMillis(watchedAt);
}
Cursor c = episodeHelper.query(episodeId, EpisodeColumns.SHOW_ID, EpisodeColumns.SEASON,
EpisodeColumns.EPISODE);
c.moveToFirst();
final long showId = Cursors.getLong(c, EpisodeColumns.SHOW_ID);
final long traktId = showHelper.getTraktId(showId);
final int season = Cursors.getInt(c, EpisodeColumns.SEASON);
final int number = Cursors.getInt(c, EpisodeColumns.EPISODE);
c.close();
episodeHelper.setWatched(showId, episodeId, watched, watchedAtMillis);
queue(new WatchedEpisode(traktId, season, number, watched, watchedAt));
}
});
}
public void checkin(final long episodeId, final String message, final boolean facebook,
final boolean twitter, final boolean tumblr) {
execute(new Runnable() {
@Override public void run() {
Cursor c = context.getContentResolver().query(Episodes.EPISODE_WATCHING, new String[] {
EpisodeColumns.ID, EpisodeColumns.EXPIRES_AT,
}, null, null, null);
final long currentTime = System.currentTimeMillis();
long expires = 0;
if (c.moveToFirst()) {
expires = Cursors.getLong(c, EpisodeColumns.EXPIRES_AT);
}
if (c.getCount() == 0 || (expires >= currentTime && expires > 0)) {
Cursor episode = episodeHelper.query(episodeId, EpisodeColumns.TRAKT_ID);
episode.moveToFirst();
final long traktId = Cursors.getLong(episode, EpisodeColumns.TRAKT_ID);
episode.close();
final long showId = episodeHelper.getShowId(episodeId);
Cursor show = context.getContentResolver().query(Shows.withId(showId), new String[] {
ShowColumns.RUNTIME,
}, null, null, null);
show.moveToFirst();
final int runtime = Cursors.getInt(show, ShowColumns.RUNTIME);
show.close();
final long startedAt = currentTime;
final long expiresAt = startedAt + runtime * DateUtils.MINUTE_IN_MILLIS;
ContentValues cv = new ContentValues();
cv.put(EpisodeColumns.CHECKED_IN, true);
cv.put(EpisodeColumns.STARTED_AT, startedAt);
cv.put(EpisodeColumns.EXPIRES_AT, expiresAt);
context.getContentResolver().update(Episodes.withId(episodeId), cv, null, null);
queue(new CheckInEpisode(traktId, message, facebook, twitter, tumblr));
}
c.close();
queue(new SyncWatching());
}
});
}
/**
* Add episodes to user library collection.
*
* @param episodeId The database id of the episode.
*/
public void setIsInCollection(final long episodeId, final boolean inCollection) {
execute(new Runnable() {
@Override public void run() {
String collectedAt = null;
long collectedAtMillis = 0L;
if (inCollection) {
collectedAt = TimeUtils.getIsoTime();
collectedAtMillis = TimeUtils.getMillis(collectedAt);
}
Cursor c = episodeHelper.query(episodeId, EpisodeColumns.SHOW_ID, EpisodeColumns.SEASON,
EpisodeColumns.EPISODE);
c.moveToFirst();
final long showId = Cursors.getLong(c, EpisodeColumns.SHOW_ID);
final long traktId = showHelper.getTraktId(showId);
final int season = Cursors.getInt(c, EpisodeColumns.SEASON);
final int number = Cursors.getInt(c, EpisodeColumns.EPISODE);
c.close();
episodeHelper.setInCollection(episodeId, inCollection, collectedAtMillis);
queue(new CollectEpisode(traktId, season, number, inCollection, collectedAt));
}
});
}
public void setIsInWatchlist(final long episodeId, final boolean inWatchlist) {
execute(new Runnable() {
@Override public void run() {
String listedAt = null;
long listeddAtMillis = 0L;
if (inWatchlist) {
listedAt = TimeUtils.getIsoTime();
listeddAtMillis = TimeUtils.getMillis(listedAt);
}
Cursor c = episodeHelper.query(episodeId, EpisodeColumns.SHOW_ID, EpisodeColumns.SEASON,
EpisodeColumns.EPISODE);
c.moveToFirst();
final long showId = Cursors.getLong(c, EpisodeColumns.SHOW_ID);
final long traktId = showHelper.getTraktId(showId);
final int season = Cursors.getInt(c, EpisodeColumns.SEASON);
final int number = Cursors.getInt(c, EpisodeColumns.EPISODE);
c.close();
episodeHelper.setIsInWatchlist(episodeId, inWatchlist, listeddAtMillis);
queue(new WatchlistEpisode(traktId, season, number, inWatchlist, listedAt));
}
});
}
/**
* Rate an episode on trakt. Depending on the user settings, this will also send out social
* updates to facebook,
* twitter, and tumblr.
*
* @param episodeId The database id of the episode.
* @param rating A rating betweeo 1 and 10. Use 0 to undo rating.
*/
public void rate(final long episodeId, final int rating) {
execute(new Runnable() {
@Override public void run() {
String ratedAt = TimeUtils.getIsoTime();
long ratedAtMillis = TimeUtils.getMillis(ratedAt);
final long showId = episodeHelper.getShowId(episodeId);
final long showTraktId = showHelper.getTraktId(showId);
Cursor c = episodeHelper.query(episodeId, EpisodeColumns.EPISODE, EpisodeColumns.SEASON);
if (c.moveToFirst()) {
final int episode = Cursors.getInt(c, EpisodeColumns.EPISODE);
final int season = Cursors.getInt(c, EpisodeColumns.SEASON);
ContentValues cv = new ContentValues();
cv.put(EpisodeColumns.USER_RATING, rating);
cv.put(EpisodeColumns.RATED_AT, ratedAtMillis);
context.getContentResolver().update(Episodes.withId(episodeId), cv, null, null);
queue(new RateEpisode(showTraktId, season, episode, rating, ratedAt));
}
c.close();
}
});
}
public void syncComments(final long episodeId) {
execute(new Runnable() {
@Override public void run() {
final long showId = episodeHelper.getShowId(episodeId);
final long traktId = showHelper.getTraktId(showId);
final int season = episodeHelper.getSeason(episodeId);
final int episode = episodeHelper.getNumber(episodeId);
queue(new SyncComments(ItemType.EPISODE, traktId, season, episode));
ContentValues values = new ContentValues();
values.put(EpisodeColumns.LAST_COMMENT_SYNC, System.currentTimeMillis());
context.getContentResolver().update(Episodes.withId(episodeId), values, null, null);
}
});
}
}