package org.envirocar.app.handler;
import android.content.Context;
import org.envirocar.core.UserManager;
import org.envirocar.core.entity.Track;
import org.envirocar.core.exception.DataRetrievalFailureException;
import org.envirocar.core.exception.DataUpdateFailureException;
import org.envirocar.core.exception.NoMeasurementsException;
import org.envirocar.core.exception.NotConnectedException;
import org.envirocar.core.exception.TrackSerializationException;
import org.envirocar.core.exception.UnauthorizedException;
import org.envirocar.core.injection.InjectApplicationScope;
import org.envirocar.core.logging.Logger;
import org.envirocar.core.util.TrackMetadata;
import org.envirocar.core.util.Util;
import org.envirocar.remote.DAOProvider;
import org.envirocar.storage.EnviroCarDB;
import java.util.ArrayList;
import javax.inject.Inject;
import javax.inject.Singleton;
import rx.Observable;
import rx.Subscriber;
import rx.exceptions.OnErrorThrowable;
import rx.schedulers.Schedulers;
/**
* TODO JavaDoc
*
* @author dewall
*/
@Singleton
public class TrackDAOHandler {
private static final Logger LOGGER = Logger.getLogger(TrackDAOHandler.class);
private final Context context;
private final UserManager userManager;
private final EnviroCarDB enviroCarDB;
private final DAOProvider daoProvider;
@Inject
public TrackDAOHandler(@InjectApplicationScope Context context, UserManager userManager,
DAOProvider daoProvider, EnviroCarDB enviroCarDB) {
this.context = context;
this.userManager = userManager;
this.enviroCarDB = enviroCarDB;
this.daoProvider = daoProvider;
}
public Observable<Track> deleteLocalTrackObservable(Track track) {
return enviroCarDB.deleteTrackObservable(track);
}
/**
* Deletes a track and returns true if the track has been successfully deleted.
*
* @param trackID the id of the track to delete.
* @return true if the track has been successfully deleted.
*/
public boolean deleteLocalTrack(Track.TrackId trackID) {
return deleteLocalTrack(
enviroCarDB.getTrack(trackID)
.subscribeOn(Schedulers.io())
.toBlocking()
.first());
}
/**
* Deletes a track and returns true if the track has been successfully deleted.
*
* @param trackRef the reference of the track.
* @return true if the track has been successfully deleted.
*/
public boolean deleteLocalTrack(Track trackRef) {
LOGGER.info(String.format("deleteLocalTrack(id = %s)", trackRef.getTrackID().getId()));
// Only delete the track if the track is a local track.
if (trackRef.isLocalTrack()) {
LOGGER.info("deleteLocalTrack(...): Track is a local track.");
enviroCarDB.deleteTrack(trackRef);
return true;
}
LOGGER.warn("deleteLocalTrack(...): track is no local track. No deletion.");
return false;
}
/**
* Invokes the deletion of a remote track. Once the remote track has been successfully
* deleted, this method also deletes the locally stored reference of that track.
*
* @param trackRef
* @return
* @throws UnauthorizedException
* @throws NotConnectedException
*/
public boolean deleteRemoteTrack(Track trackRef) throws UnauthorizedException,
NotConnectedException {
LOGGER.info(String.format("deleteRemoteTrack(id = %s)", trackRef.getTrackID().getId()));
// Check whether this track is a remote track.
if (!trackRef.isRemoteTrack()) {
LOGGER.warn("Track reference to upload is no remote track.");
return false;
}
// Delete the track first remote and then the local reference.
try {
daoProvider.getTrackDAO().deleteTrack(trackRef);
} catch (DataUpdateFailureException e) {
e.printStackTrace();
}
enviroCarDB.deleteTrack(trackRef);
// Successfully deleted the remote track.
LOGGER.info("deleteRemoteTrack(): Successfully deleted the remote track.");
return true;
}
public boolean deleteAllRemoteTracksLocally() {
LOGGER.info("deleteAllRemoteTracksLocally()");
enviroCarDB.deleteAllRemoteTracks()
.subscribeOn(Schedulers.io())
.toBlocking()
.first();
return true;
}
public Observable<Integer> getLocalTrackCount(){
return enviroCarDB.getAllLocalTracks(true)
.map(tracks -> tracks.size());
}
public Observable<TrackMetadata> updateTrackMetadataObservable(Track track) {
return Observable.just(track)
.map(track1 -> new TrackMetadata(Util.getVersionString(context),
userManager.getUser().getTermsOfUseVersion()))
.flatMap(trackMetadata -> updateTrackMetadata(track
.getTrackID(),
trackMetadata));
}
public Observable<TrackMetadata> updateTrackMetadata(
Track.TrackId trackId, TrackMetadata trackMetadata) {
return enviroCarDB.getTrack(trackId, true)
.map(track -> {
TrackMetadata result = track.updateMetadata(trackMetadata);
enviroCarDB.updateTrack(track);
return result;
});
}
public Observable<Track> fetchRemoteTrackObservable(Track remoteTrack) {
return Observable.create(new Observable.OnSubscribe<Track>() {
@Override
public void call(Subscriber<? super Track> subscriber) {
try {
subscriber.onNext(fetchRemoteTrack(remoteTrack));
subscriber.onCompleted();
} catch (NotConnectedException e) {
throw OnErrorThrowable.from(e);
} catch (DataRetrievalFailureException e) {
throw OnErrorThrowable.from(e);
} catch (UnauthorizedException e) {
throw OnErrorThrowable.from(e);
}
}
});
}
public Track fetchRemoteTrack(Track remoteTrack) throws NotConnectedException,
UnauthorizedException, DataRetrievalFailureException {
try {
Track downloadedTrack = daoProvider.getTrackDAO().getTrackById(remoteTrack
.getRemoteID());
// Deep copy... TODO improve this.
remoteTrack.setName(downloadedTrack.getName());
remoteTrack.setDescription(downloadedTrack.getDescription());
remoteTrack.setMeasurements(new ArrayList<>(downloadedTrack.getMeasurements()));
remoteTrack.setCar(downloadedTrack.getCar());
remoteTrack.setTrackStatus(downloadedTrack.getTrackStatus());
remoteTrack.setMetadata(downloadedTrack.getMetadata());
remoteTrack.setStartTime(downloadedTrack.getStartTime());
remoteTrack.setEndTime(downloadedTrack.getEndTime());
remoteTrack.setDownloadState(Track.DownloadState.DOWNLOADED);
} catch (NoMeasurementsException e) {
e.printStackTrace();
}
try {
enviroCarDB.insertTrack(remoteTrack);
} catch (TrackSerializationException e) {
e.printStackTrace();
}
// mDBAdapter.insertTrack(remoteTrack, true);
return remoteTrack;
}
}