package org.sugr.gearshift.service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.support.v4.content.LocalBroadcastManager;
import org.sugr.gearshift.G;
import org.sugr.gearshift.core.Torrent;
import org.sugr.gearshift.core.TransmissionProfile;
import org.sugr.gearshift.core.TransmissionSession;
import java.util.ArrayList;
public class DataServiceManager {
private Context context;
private TransmissionProfile profile;
private int iteration;
private boolean details;
private boolean isStopped;
private boolean isLastErrorFatal;
private boolean sessionOnly;
private String[] torrentsToUpdate;
private ServiceReceiver serviceReceiver;
private Handler updateHandler = new Handler();
private Runnable updateRunnable = new Runnable() {
@Override public void run() {
synchronized (DataServiceManager.this) {
if (!isStopped) {
update();
}
}
}
};
private static final String STATE_ITERATION = "data_service_iteration";
public DataServiceManager(Context context, TransmissionProfile profile) {
this.context = context;
this.profile = profile;
iteration = 0;
serviceReceiver = new ServiceReceiver();
}
public DataServiceManager onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putInt(STATE_ITERATION, iteration);
return this;
}
public DataServiceManager onRestoreInstanceState(Bundle savedInstanceState) {
if (savedInstanceState != null) {
if (savedInstanceState.containsKey(STATE_ITERATION)) {
iteration = savedInstanceState.getInt(STATE_ITERATION);
}
}
return this;
}
public DataServiceManager reset() {
iteration = 0;
stopUpdating();
Intent intent = new Intent(context, DataService.class);
context.stopService(intent);
return this;
}
public DataServiceManager setDetails(boolean details) {
this.details = details;
return this;
}
public DataServiceManager setSessionOnly(boolean sessionOnly) {
this.sessionOnly = sessionOnly;
return this;
}
public DataServiceManager setTorrentsToUpdate(String[] hashStrings) {
torrentsToUpdate = hashStrings;
update();
return this;
}
public DataServiceManager startUpdating() {
synchronized (this) {
isStopped = false;
LocalBroadcastManager.getInstance(context).registerReceiver(serviceReceiver,
new IntentFilter(G.INTENT_SERVICE_ACTION_COMPLETE));
}
isLastErrorFatal = false;
update();
return this;
}
public DataServiceManager stopUpdating() {
synchronized (this) {
isStopped = true;
LocalBroadcastManager.getInstance(context).unregisterReceiver(serviceReceiver);
}
return this;
}
public void update() {
update(false);
}
public void update(boolean updateAllDetails) {
updateHandler.removeCallbacks(updateRunnable);
if (sessionOnly) {
getSession();
} else {
boolean active = profile.updateActiveTorrentsOnly();
int fullUpdate = profile.getFullUpdate();
String requestType = DataService.Requests.GET_TORRENTS;
Bundle args = new Bundle();
if (active && !details && iteration % fullUpdate != 0) {
args.putBoolean(DataService.Args.UPDATE_ACTIVE, true);
}
if (details || iteration == 1) {
args.putBoolean(DataService.Args.DETAIL_FIELDS, true);
}
if (updateAllDetails) {
args.putBoolean(DataService.Args.ALL_TORRENT_FIELDS, true);
}
if (torrentsToUpdate != null) {
args.putStringArray(DataService.Args.TORRENTS_TO_UPDATE, torrentsToUpdate);
}
if (iteration == 0 || isLastErrorFatal) {
args.putBoolean(DataService.Args.REMOVE_OBSOLETE, true);
}
if (iteration % 3 == 0) {
getSession();
}
Intent intent = createIntent(requestType, args);
context.startService(intent);
}
iteration++;
isLastErrorFatal = false;
}
public DataServiceManager getSession() {
context.startService(createIntent(DataService.Requests.GET_SESSION, null));
return this;
}
public DataServiceManager setSession(TransmissionSession session, String... fields) {
Bundle args = new Bundle();
args.putParcelable(DataService.Args.SESSION, session);
args.putStringArray(DataService.Args.SESSION_FIELDS, fields);
Intent intent = createIntent(DataService.Requests.SET_SESSION, args);
context.startService(intent);
return this;
}
public DataServiceManager addTorrent(String profile, String magnet, String temporaryFile, String torrentFile,
String location, boolean addPaused, Uri documentUri) {
Bundle args = new Bundle();
args.putString(DataService.Args.MAGNET_URI, magnet);
args.putString(DataService.Args.TORRENT_DATA_PATH, temporaryFile);
args.putString(DataService.Args.TORRENT_FILE, torrentFile);
args.putString(DataService.Args.LOCATION, location);
args.putBoolean(DataService.Args.ADD_PAUSED, addPaused);
args.putParcelable(DataService.Args.DOCUMENT_URI, documentUri);
Intent intent = createIntent(DataService.Requests.ADD_TORRENT, args);
intent.putExtra(G.ARG_PROFILE_ID, profile);
context.startService(intent);
return this;
}
public DataServiceManager removeTorrent(String[] hashStrings, boolean deleteData) {
Bundle args = new Bundle();
args.putStringArray(DataService.Args.HASH_STRINGS, hashStrings);
args.putBoolean(DataService.Args.DELETE_DATA, deleteData);
Intent intent = createIntent(DataService.Requests.REMOVE_TORRENT, args);
context.startService(intent);
return this;
}
public DataServiceManager setTorrent(String[] hashStrings, String field, int value) {
Bundle args = new Bundle();
args.putInt(DataService.Args.TORRENT_FIELD_VALUE, value);
return setTorrent(hashStrings, field, args);
}
public DataServiceManager setTorrent(String[] hashStrings, String field, long value) {
Bundle args = new Bundle();
args.putLong(DataService.Args.TORRENT_FIELD_VALUE, value);
return setTorrent(hashStrings, field, args);
}
public DataServiceManager setTorrent(String[] hashStrings, String field, boolean value) {
Bundle args = new Bundle();
args.putBoolean(DataService.Args.TORRENT_FIELD_VALUE, value);
return setTorrent(hashStrings, field, args);
}
public DataServiceManager setTorrent(String[] hashStrings, String field, float value) {
Bundle args = new Bundle();
args.putFloat(DataService.Args.TORRENT_FIELD_VALUE, value);
return setTorrent(hashStrings, field, args);
}
@SuppressWarnings("unchecked")
public DataServiceManager setTorrent(String[] hashStrings, String field, ArrayList<?> value) {
Bundle args = new Bundle();
switch (field) {
case Torrent.SetterFields.FILES_WANTED:
case Torrent.SetterFields.FILES_UNWANTED:
case Torrent.SetterFields.FILES_LOW:
case Torrent.SetterFields.FILES_NORMAL:
case Torrent.SetterFields.FILES_HIGH:
case Torrent.SetterFields.TRACKER_REMOVE:
args.putIntegerArrayList(DataService.Args.TORRENT_FIELD_VALUE, (ArrayList<Integer>) value);
break;
case Torrent.SetterFields.TRACKER_ADD:
case Torrent.SetterFields.TRACKER_REPLACE:
args.putStringArrayList(DataService.Args.TORRENT_FIELD_VALUE, (ArrayList<String>) value);
break;
}
return setTorrent(hashStrings, field, args);
}
public DataServiceManager setTorrentLocation(String[] hashStrings, String location, boolean move) {
Bundle args = new Bundle();
args.putStringArray(DataService.Args.HASH_STRINGS, hashStrings);
args.putString(DataService.Args.LOCATION, location);
args.putBoolean(DataService.Args.MOVE_DATA, move);
Intent intent = createIntent(DataService.Requests.SET_TORRENT_LOCATION, args);
context.startService(intent);
return this;
}
public DataServiceManager setTorrentAction(String[] hashStrings, G.TorrentAction action) {
Bundle args = new Bundle();
args.putStringArray(DataService.Args.HASH_STRINGS, hashStrings);
args.putString(DataService.Args.TORRENT_ACTION, action.action());
Intent intent = createIntent(DataService.Requests.SET_TORRENT_ACTION, args);
context.startService(intent);
return this;
}
public DataServiceManager removeProfile() {
Intent intent = createIntent(DataService.Requests.REMOVE_PROFILE, null);
context.startService(intent);
return this;
}
public DataServiceManager getFreeSpace(String location) {
Bundle args = new Bundle();
args.putString(DataService.Args.LOCATION, location);
Intent intent = createIntent(DataService.Requests.GET_FREE_SPACE, args);
context.startService(intent);
return this;
}
public DataServiceManager testPort() {
Intent intent = createIntent(DataService.Requests.TEST_PORT, null);
context.startService(intent);
return this;
}
public DataServiceManager updateBlocklist() {
Intent intent = createIntent(DataService.Requests.UPDATE_BLOCKLIST, null);
context.startService(intent);
return this;
}
private SharedPreferences getPreferences() {
return PreferenceManager.getDefaultSharedPreferences(context);
}
private Intent createIntent(String requestType, Bundle args) {
Intent intent = new Intent(context, DataService.class);
intent.putExtra(G.ARG_PROFILE_ID, profile.getId());
intent.putExtra(G.ARG_REQUEST_TYPE, requestType);
intent.putExtra(G.ARG_REQUEST_ARGS, args == null ? new Bundle() : args);
return intent;
}
private void repeatLoading() {
int update = profile.getUpdateInterval();
if (update >= 0 && !isStopped) {
if (sessionOnly && update < 10) {
update = 10;
}
updateHandler.postDelayed(updateRunnable, update * 1000);
}
}
private DataServiceManager setTorrent(String[] hashStrings, String field, Bundle args) {
args.putStringArray(DataService.Args.HASH_STRINGS, hashStrings);
args.putString(DataService.Args.TORRENT_FIELD, field);
Intent intent = createIntent(DataService.Requests.SET_TORRENT, args);
context.startService(intent);
return this;
}
private class ServiceReceiver extends BroadcastReceiver {
@Override public void onReceive(Context context, Intent intent) {
int error = intent.getIntExtra(G.ARG_ERROR, 0);
if (error == 0 || error == DataService.Errors.DUPLICATE_TORRENT
|| error == DataService.Errors.INVALID_TORRENT) {
String type = intent.getStringExtra(G.ARG_REQUEST_TYPE);
switch (type) {
case DataService.Requests.GET_TORRENTS:
repeatLoading();
break;
case DataService.Requests.ADD_TORRENT:
update(true);
break;
}
} else {
isLastErrorFatal = true;
}
}
}
}