package com.androideasyapps.phoenix.sync; import com.androideasyapps.phoenix.dao.H2PersistenceManager; import com.androideasyapps.phoenix.dao.MediaFile; import com.androideasyapps.phoenix.dao.MediaFileH2DAO; import com.androideasyapps.phoenix.services.sagetv.SageTVService; import com.androideasyapps.phoenix.services.sagetv.model.MediaFileResults; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Future; import rx.Observable; import rx.Subscriber; import rx.schedulers.Schedulers; import static com.androideasyapps.phoenix.util.MediaUtil.getFileCount; import static com.androideasyapps.phoenix.util.MediaUtil.getFileName; import static com.androideasyapps.phoenix.util.MediaUtil.getGenres; import static com.androideasyapps.phoenix.util.MediaUtil.isTVAiring; import static com.androideasyapps.phoenix.util.MediaUtil.isTVSeason; import static com.androideasyapps.phoenix.util.Util.firstNonNull; import static com.androideasyapps.phoenix.util.Util.parseInt; /** * Created by seans on 20/12/14. */ public class SageTVSync { private static final Logger log = LoggerFactory.getLogger(SageTVSync.class); public Observable<MediaFile> syncCollection(final SageTVService service, final Future<H2PersistenceManager> persistenceManagerFuture, SyncOptions options) { final SyncOptions opts = (options==null?new SyncOptions():options); return Observable.create(new Observable.OnSubscribe<MediaFile>() { @Override public void call(Subscriber<? super MediaFile> subscriber) { final MediaFileH2DAO dao; log.info("Starting SageTV Sync"); int last = 0; int size = 50; if (subscriber.isUnsubscribed()) return; subscriber.onStart(); try { dao = persistenceManagerFuture.get().getMediaFileDAO(); if (opts.isEraseCollection()) { dao.deleteAll(); } } catch (Exception e) { log.error("Failed to get Persistence Manager", e); subscriber.onError(e); return; } try { List<Long> sageids = new ArrayList<Long>(); while (true) { log.info("Processing {}-{} items", last, last + size); // do this in chunks of 100 untile we have everything... MediaFileResults results = service.getMediaFiles("TV", last, size); if (results == null || results.getResult() == null || results.getResult().size() == 0) { // we are done break; } MediaFile existingMF=null; MediaFile mfdao = null; for (com.androideasyapps.phoenix.services.sagetv.model.MediaFile mf : results.getResult()) { //System.out.println("MF: " + mf.MediaFileMetadataProperties.MediaTitle); if (mf.Airing == null) { log.warn("Airing is Null for: {}", mf.MediaFileID); continue; } if (mf.MediaFileID == 0) { continue; } if (mf.Airing.Show == null) { log.warn("Airing.Show is Null for: {}", mf.MediaFileID); continue; } sageids.add(mf.MediaFileID); existingMF = null; try { existingMF = dao.queryFirst("mediafileid=?", mf.MediaFileID); } catch (Exception e) { log.error("Failed which finding {}", mf.MediaFileID, e); continue; } if (existingMF!=null) { mfdao = existingMF; } else { mfdao = new MediaFile(); } String mediaType = mf.MediaFileMetadataProperties.MediaType; if (mediaType == null || mediaType.trim().length()==0) { String file = getFileName(mf); if (file == null) { log.warn("No Physical File, Skipping: {}", mf.MediaFileID); continue; } else { // missing metadata log.warn("MediaType was null for {} - {}; Will Auto Determine Type.", mf.MediaFileID, file); if (isTVAiring(file) || isTVSeason(file)) { mfdao.setMediaType("TV"); } else { mfdao.setMediaType("MOVIE"); } } mfdao.setHasmetadata(false); } else { mfdao.setHasmetadata(true); } mfdao.setGenre(getGenres(mf.Airing.Show.ShowCategoriesList)); mfdao.setDescription(firstNonNull(mf.MediaFileMetadataProperties.Description, mf.Airing.Show.ShowDescription)); mfdao.setDuration(mf.Airing.AiringDuration); mfdao.setEpisode(parseInt(firstNonNull(mf.MediaFileMetadataProperties.EpisodeNumber, mf.Airing.Show.ShowEpisodeNumber))); mfdao.setSeason(parseInt(firstNonNull(mf.MediaFileMetadataProperties.SeasonNumber, mf.Airing.Show.ShowSeasonNumber))); mfdao.setEpisodeTitle(mf.MediaFileMetadataProperties.EpisodeName); mfdao.setFileDate(mf.FileStartTime); mfdao.setMediaFileId(mf.MediaFileID); mfdao.setMediaType(mf.MediaFileMetadataProperties.MediaType); mfdao.setOriginalAirDate(mf.Airing.AiringStartTime); mfdao.setTitle(firstNonNull(mf.MediaFileMetadataProperties.MediaTitle, mf.Airing.Show.ShowEpisode, mf.MediaFileRelativePath)); mfdao.setUserRating(parseInt(mf.MediaFileMetadataProperties.UserRating)); mfdao.setWatched(mf.Airing.IsWatched); mfdao.setYear(parseInt(firstNonNull(mf.MediaFileMetadataProperties.Year, mf.Airing.Show.ShowYear))); mfdao.setRating(mf.MediaFileMetadataProperties.Rated); mfdao.setParts(getFileCount(mf)); if (mfdao.getTitle() == null) { log.warn("Null Title for {} - {}; Skipping.", mf.MediaFileID, getFileName(mf)); continue; } if (mfdao.getMediaType() == null) { mfdao.setMediaType("MOVIE"); } mfdao.setMediaType(mfdao.getMediaType().trim().toLowerCase()); try { dao.save(mfdao); } catch (Exception e) { e.printStackTrace(); } if (!subscriber.isUnsubscribed()) { subscriber.onNext(mfdao); } } last += size; } // delete the deleted ones if (sageids.size()>0) { StringBuilder sb = new StringBuilder("mediatype in ('tv','movie') and mediafileid not in ("); for (int i=0;i<sageids.size();i++) { if (i>0) { sb.append(","); } sb.append(String.valueOf(sageids.get(i))); } sb.append(")"); log.info("DELETING: " + sb.toString()); dao.deleteWhere(sb.toString()); } // clear the ids sageids.clear(); } catch (Throwable t) { log.error("Sync Failed", t); if (!subscriber.isUnsubscribed()) subscriber.onError(t); } finally { if (!subscriber.isUnsubscribed()) subscriber.onCompleted(); } } } ). subscribeOn(Schedulers.io() ); } }