/*
This file is part of JFLICKS.
JFLICKS is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
JFLICKS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with JFLICKS. If not, see <http://www.gnu.org/licenses/>.
*/
package org.jflicks.autoart.system;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.jflicks.autoart.BaseAutoArt;
import org.jflicks.autoart.SearchItem;
import org.jflicks.db.DbWorker;
import org.jflicks.metadata.themoviedb.Artwork;
import org.jflicks.metadata.themoviedb.Genre;
import org.jflicks.metadata.themoviedb.Image;
import org.jflicks.metadata.themoviedb.Movie;
import org.jflicks.metadata.themoviedb.Search;
import org.jflicks.metadata.themoviedb.TheMovieDB;
import org.jflicks.nms.NMS;
import org.jflicks.util.LogUtil;
import com.db4o.ObjectContainer;
import com.db4o.ObjectSet;
import com.db4o.osgi.Db4oService;
import com.db4o.query.Predicate;
import com.moviejukebox.thetvdb.TheTVDB;
import com.moviejukebox.thetvdb.model.Banner;
import com.moviejukebox.thetvdb.model.Banners;
import com.moviejukebox.thetvdb.model.Episode;
import com.moviejukebox.thetvdb.model.Series;
/**
* This is our implementation of an AutoArt service.
*
* @author Doug Barnum
* @version 1.0
*/
public class SystemAutoArt extends BaseAutoArt implements DbWorker {
private static final String KEY = "DD342FB4D55DF7BB";
private ObjectContainer objectContainer;
private Db4oService db4oService;
private TheTVDB theTVDB;
/**
* Default empty constructor.
*/
public SystemAutoArt() {
setTitle("SystemAutoArt");
}
/**
* We use the Db4oService to persist the configuration data.
*
* @return A Db4oService instance.
*/
public Db4oService getDb4oService() {
return (db4oService);
}
/**
* We use the Db4oService to persist the configuration data.
*
* @param s A Db4oService instance.
*/
public void setDb4oService(Db4oService s) {
db4oService = s;
}
private TheTVDB getTheTVDB() {
return (theTVDB);
}
private void setTheTVDB(TheTVDB tvdb) {
theTVDB = tvdb;
}
private synchronized ObjectContainer getObjectContainer() {
if (objectContainer == null) {
Db4oService s = getDb4oService();
if (s != null) {
com.db4o.config.Configuration config = s.newConfiguration();
objectContainer = s.openFile(config, "db/autoart.dat");
} else {
LogUtil.log(LogUtil.WARNING, "SystemAutoArt: Db4oService null!");
}
}
return (objectContainer);
}
private void purge(ObjectContainer db, Class c) {
if ((db != null) && (c != null)) {
ObjectSet result = db.queryByExample(c);
while (result.hasNext()) {
db.delete(result.next());
}
}
}
private void addSearchItem(SearchItem si) {
ObjectContainer oc = getObjectContainer();
if ((si != null) && (oc != null)) {
// First remove this SearchItem if it already exists.
removeSearchItem(si);
oc.store(new SearchItem(si));
oc.commit();
}
}
private void removeSearchItem(SearchItem si) {
ObjectContainer oc = getObjectContainer();
if ((si != null) && (oc != null)) {
final String id = si.getId();
List<SearchItem> sis =
oc.query(new Predicate<SearchItem>() {
public boolean match(SearchItem si) {
return (id.equals(si.getId()));
}
});
if (sis != null) {
for (int i = 0; i < sis.size(); i++) {
SearchItem tmp = sis.get(i);
oc.delete(tmp);
}
}
}
}
private SearchItem getSearchItemById(String id) {
SearchItem result = null;
ObjectContainer oc = getObjectContainer();
if (oc != null) {
final String sid = id;
List<SearchItem> items =
oc.query(new Predicate<SearchItem>() {
public boolean match(SearchItem si) {
return (sid.equals(si.getId()));
}
});
if ((items != null) && (items.size() > 0)) {
result = items.get(0);
}
}
return (result);
}
private SearchItem[] getSearchItemHistory() {
SearchItem[] result = null;
ObjectContainer oc = getObjectContainer();
if (oc != null) {
ObjectSet<SearchItem> os = oc.queryByExample(SearchItem.class);
if (os != null) {
result = os.toArray(new SearchItem[os.size()]);
}
}
return (result);
}
private boolean isReadyToSearch(SearchItem si) {
boolean result = false;
if (si != null) {
// Not more than once every three days...
long when = si.getLastCheck() + 3 * 24 * 60 * 60 * 1000;
long now = System.currentTimeMillis();
result = now > when;
}
return (result);
}
/**
* Close up all resources.
*/
public void close() {
if (objectContainer != null) {
boolean result = objectContainer.close();
LogUtil.log(LogUtil.DEBUG, "SystemAutoArt: closed " + result);
objectContainer = null;
} else {
LogUtil.log(LogUtil.DEBUG, "SystemAutoArt: Tried to close "
+ "but objectContainer null.");
}
}
private void performSearch(SearchItem si) {
// First let's try the TV database.
TheTVDB tvdb = getTheTVDB();
if (tvdb == null) {
setTheTVDB(new TheTVDB(KEY));
tvdb = getTheTVDB();
}
boolean checkMovie = true;
if ((si != null) && (tvdb != null)) {
LogUtil.log(LogUtil.DEBUG, "Searching for: " + si.getTitle());
List<Series> list = tvdb.searchSeries(si.getTitle(), "en");
LogUtil.log(LogUtil.DEBUG, "Series list: " + list);
if ((list != null) && (list.size() > 0)) {
LogUtil.log(LogUtil.DEBUG, "Series list.size(): " + list.size());
int season = si.getSeason();
int episode = si.getEpisode();
LogUtil.log(LogUtil.DEBUG, "season <" + season + "> episode <" + episode + ">");
if ((season > 0) && (episode > 0)) {
Episode epi = tvdb.getEpisode(list.get(0).getId(),
season, episode, "en");
LogUtil.log(LogUtil.DEBUG, "Episode: " + epi);
if (epi != null) {
si.setOverview("\"" + epi.getEpisodeName() + "\" "
+ epi.getOverview());
si.setReleased(epi.getFirstAired());
}
}
Banners banners = tvdb.getBanners(list.get(0).getId());
if (banners != null) {
if (si.isNeedBanner()) {
List<Banner> blist = banners.getSeriesList();
if ((blist != null) && (blist.size() > 0)) {
si.setBannerURL(blist.get(0).getUrl());
checkMovie = false;
}
}
if (si.isNeedFanart()) {
List<Banner> blist = banners.getFanartList();
if ((blist != null) && (blist.size() > 0)) {
si.setFanartURL(blist.get(0).getUrl());
checkMovie = false;
}
}
if (si.isNeedPoster()) {
List<Banner> blist = banners.getPosterList();
if ((blist != null) && (blist.size() > 0)) {
si.setPosterURL(blist.get(0).getUrl());
checkMovie = false;
}
}
}
}
if (checkMovie) {
// OK we didn't find anything with the TV database. We
// will now try using the movie database.
TheMovieDB tmdb = TheMovieDB.getInstance();
if (tmdb != null) {
Search search = tmdb.search(si.getTitle());
if (search != null) {
Movie[] array = search.getMovies();
if ((array != null) && (array.length > 0)) {
Movie m = tmdb.retrieve(array[0].getId());
if (m == null) {
// Better than nothing...
m = array[0];
}
if (m != null) {
// Set the overview and released info....
si.setOverview(m.getOverview());
si.setReleased(m.getReleaseDate());
si.setRuntime(m.getRuntime() * 60);
Genre[] garray = m.getGenres();
if ((garray != null) && (garray.length > 0)) {
si.setGenre(garray[0].getName());
}
Artwork art = m.getArtwork();
if (art != null) {
String url = null;
Image[] posters = art.getPosters();
if ((posters != null)
&& (posters.length > 0)) {
url = posters[0].getUrl();
}
if (url != null) {
si.setPosterURL(url);
}
url = null;
Image[] backs = art.getBackdrops();
if ((backs != null) && (backs.length > 0)) {
url = backs[0].getUrl();
}
if (url != null) {
si.setFanartURL(url);
}
}
}
}
}
}
}
}
}
/**
* {@inheritDoc}
*/
public void performUpdate() {
// First thing to do is a video scan...
NMS n = getNMS();
if (n != null) {
n.videoScan();
}
SearchItem[] array = getSearchItems();
if ((array != null) && (array.length > 0)) {
LogUtil.log(LogUtil.INFO, "We have " + array.length + " items missing art.");
// We have missing artwork, so we should check for new stuff.
// However we should filter it because if it was missing on
// our last run then perhaps we should wait a while before
// checking again. So we need to build a real list of
// searches to do NOW.
ArrayList<SearchItem> l = new ArrayList<SearchItem>();
for (int i = 0; i < array.length; i++) {
SearchItem si = getSearchItemById(array[i].getId());
if (si == null) {
l.add(array[i]);
} else if (isReadyToSearch(si)) {
l.add(array[i]);
}
}
LogUtil.log(LogUtil.INFO, "We are going to search for " + l.size()
+ " items at this time.");
for (int i = 0; i < l.size(); i++) {
SearchItem si = l.get(i);
LogUtil.log(LogUtil.INFO, "Searching using <" + si.getTitle() + ">");
si.setLastCheck(System.currentTimeMillis());
performSearch(si);
save(si);
addSearchItem(si);
}
}
}
}