package com.felkertech.cumulustv.utils;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import com.felkertech.cumulustv.model.ChannelDatabase;
import com.felkertech.settingsmanager.SettingsManager;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.drive.Drive;
import com.google.android.gms.drive.DriveApi;
import com.google.android.gms.drive.DriveContents;
import com.google.android.gms.drive.DriveFile;
import com.google.android.gms.drive.DriveId;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
/**
* Created by Nick on 3/22/2016.
*/
public class DriveSettingsManager extends SettingsManager {
private static final String TAG = DriveSettingsManager.class.getSimpleName();
private static final boolean DEBUG = false;
private GoogleApiClient mGoogleApiClient;
private GoogleDriveListener mGoogleDriveListener;
public DriveSettingsManager(Context context) {
super(context);
}
/* GOOGLE DRIVE */
public void setGoogleDriveSyncable(GoogleApiClient gapi) {
this.mGoogleApiClient = gapi;
}
public void setGoogleDriveSyncable(GoogleApiClient gapi, GoogleDriveListener gdl) {
this.mGoogleApiClient = gapi;
this.mGoogleDriveListener = gdl;
}
/**
* Writes some data to a Google Drive file, this can get from a preference
* @param driveId The id of the file to be written to
* @param data The string of data that should be written
*/
public void writeToGoogleDrive(DriveId driveId, String data) {
DriveFile file = Drive.DriveApi.getFile(mGoogleApiClient, driveId);
if (DEBUG) {
Log.d(TAG, "Writing to " + driveId + " -> " + data);
}
new EditGoogleDriveAsyncTask(mContext).execute(file, data);
}
public void readFromGoogleDrive(DriveId driveId, final int resId) {
readFromGoogleDrive(driveId, mContext.getString(resId));
}
/**
* Reads a file from Google Drive and inserts that data into a preference
* @param driveId The id of the file to be read from
* @param resId The key for the desired preference
*/
public void readFromGoogleDrive(DriveId driveId, final String resId) {
if(mGoogleApiClient == null || !mGoogleApiClient.isConnected()) {
return;
}
ResultCallback<DriveApi.DriveContentsResult> driveContentsCallback =
new ResultCallback<DriveApi.DriveContentsResult>() {
@Override
public void onResult(DriveApi.DriveContentsResult result) {
if (!result.getStatus().isSuccess()) {
if (DEBUG) {
Log.d(TAG, "Error while opening the file contents");
}
return;
}
if (DEBUG) {
Log.d(TAG, "File contents opened");
}
//Now step 2, build the contents
try {
DriveContents contents = result.getDriveContents();
BufferedReader reader = new BufferedReader(
new InputStreamReader(contents.getInputStream()));
StringBuilder builder = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
builder.append(line);
}
String contentsAsString = builder.toString();
if (DEBUG) {
Log.d(TAG, "From " + contents.getDriveId());
Log.d(TAG, "Retrieved " + contentsAsString);
}
// Step 2.5, check if it is valid
try {
JSONObject tempJson = new JSONObject(contentsAsString);
} catch (JSONException e) {
throw new ChannelDatabase.MalformedChannelDataException(
e.getMessage() + " User Data: '" + contentsAsString + "'");
}
//Step 3, write to SM
setString(resId, contentsAsString);
//Step 4, close stream (or not? java.lang.IllegalStateException: Cannot commit contents opened with MODE_READ_ONLY)
/*contents.commit(mGoogleApiClient, null).setResultCallback(new ResultCallback<Status>() {
@Override
public void onResult(Status result) {
// handle the response status
}
});*/
//Step 5, send alert
if(mGoogleDriveListener != null) {
Handler h = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
mGoogleDriveListener.onActionFinished(true);
}
};
h.sendEmptyMessage(0);
}
} catch (IOException e) {
e.printStackTrace();
}
}
};
Drive.DriveApi.getFile(mGoogleApiClient, driveId)
.open(mGoogleApiClient, DriveFile.MODE_READ_ONLY, null)
.setResultCallback(driveContentsCallback);
}
public class EditGoogleDriveAsyncTask extends AsyncTask<Object, Void, Boolean> {
DriveContents driveContents;
public EditGoogleDriveAsyncTask(Context context) {
super();
}
@Override
protected Boolean doInBackground(Object... args) {
DriveFile file = (DriveFile) args[0];
String data = (String) args[1];
try {
DriveApi.DriveContentsResult driveContentsResult = file.open(
mGoogleApiClient, DriveFile.MODE_WRITE_ONLY, null).await();
if (!driveContentsResult.getStatus().isSuccess()) {
return false;
}
driveContents = driveContentsResult.getDriveContents();
OutputStream outputStream = driveContents.getOutputStream();
outputStream.write(data.getBytes());
com.google.android.gms.common.api.Status status =
driveContents.commit(mGoogleApiClient, null).await();
if(mGoogleDriveListener != null) {
Handler h = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
mGoogleDriveListener.onActionFinished(false);
}
};
h.sendEmptyMessage(0);
}
return status.getStatus().isSuccess();
} catch (IOException e) {
if (DEBUG) {
Log.e(TAG, "IOException while appending to the output stream", e);
}
}
return false;
}
@Override
protected void onPostExecute(Boolean result) {
if (DEBUG) {
Log.d(TAG, "EditContents result " + result);
}
/*driveContents.commit(mGoogleApiClient, null).setResultCallback(new ResultCallback<com.google.android.gms.common.api.Status>() {
@Override
public void onResult(com.google.android.gms.common.api.Status result) {
// Handle the response status
}
});*/
}
}
public interface GoogleDriveListener {
void onActionFinished(boolean cloudToLocal);
}
}