package com.openfarmanager.android.core.network.skydrive;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.database.Cursor;
import com.mediafire.sdk.api.responses.data_models.FileInfo;
import com.microsoft.live.*;
import com.openfarmanager.android.App;
import com.openfarmanager.android.R;
import com.openfarmanager.android.core.DataStorageHelper;
import com.openfarmanager.android.core.dbadapters.NetworkAccountDbAdapter;
import com.openfarmanager.android.core.network.NetworkApi;
import com.openfarmanager.android.filesystem.FileProxy;
import com.openfarmanager.android.filesystem.FileSystemScanner;
import com.openfarmanager.android.filesystem.SkyDriveFile;
import com.openfarmanager.android.model.NetworkAccount;
import com.openfarmanager.android.model.NetworkEnum;
import com.openfarmanager.android.model.exeptions.NetworkException;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import static com.openfarmanager.android.utils.Extensions.*;
import java.io.*;
import java.net.URL;
import java.util.*;
/**
* @author Vlad Namashko
*/
public class SkyDriveAPI implements LiveAuthListener, NetworkApi {
public static String APP_CLIENT_ID = "00000000440FC95F";
public static String APP_CLIENT_SECRET = "PGdXoSKea7BFGZDUa4VRRrjVKbhasZtm";
public static final String SKYDRIVE_ACCESS_TOKEN = "skydrive_access_token";
public static final String SKYDRIVE_REFRESH_TOKEN = "skydrive_refresh_token";
protected LiveAuthClient mSkyDriveAuthClient;
protected LiveConnectClient mSkyDriveConnectClient;
private Activity mAuthActivity;
private SkyDriveAccount mCurrentSkyDriveAccount;
// private final static byte[] BUFFER = new byte[256 * 1024];
public OnLoginListener mOnLoginListener;
private String mDriveDefaultPath;
public static final String[] SCOPES = {
"wl.signin",
"wl.basic",
"wl.offline_access",
"wl.skydrive_update"
};
public SkyDriveAPI() {
mSkyDriveAuthClient = new LiveAuthClient(App.sInstance, SkyDriveAPI.APP_CLIENT_ID);
}
public int getAuthorizedAccountsCount() {
return NetworkAccountDbAdapter.count(NetworkEnum.SkyDrive.ordinal());
}
@Override
public List<NetworkAccount> getAuthorizedAccounts() {
List<NetworkAccount> accounts = new ArrayList<NetworkAccount>();
Cursor cursor = NetworkAccountDbAdapter.getAccounts(NetworkEnum.SkyDrive.ordinal());
if (cursor == null) {
return accounts;
}
try {
int idxId = cursor.getColumnIndex(NetworkAccountDbAdapter.Columns.ID);
int idxUserName = cursor.getColumnIndex(NetworkAccountDbAdapter.Columns.USER_NAME);
int idxAuthData = cursor.getColumnIndex(NetworkAccountDbAdapter.Columns.AUTH_DATA);
while(cursor.moveToNext()) {
String authData = cursor.getString(idxAuthData);
try {
JSONObject data = new JSONObject(authData);
SkyDriveAccount account = new SkyDriveAccount(cursor.getLong(idxId), cursor.getString(idxUserName),
data.getString(SKYDRIVE_REFRESH_TOKEN));
accounts.add(account);
} catch (JSONException e) {
e.printStackTrace();
}
}
} finally {
cursor.close();
DataStorageHelper.closeDatabase();
}
return accounts;
}
@Override
public NetworkAccount newAccount() {
return new SkyDriveAccount(-1, App.sInstance.getResources().getString(com.openfarmanager.android.R.string.btn_new), (String) null);
}
@Override
public NetworkAccount getCurrentNetworkAccount() {
return mCurrentSkyDriveAccount;
}
@Override
public void delete(FileProxy file) throws Exception {
mSkyDriveConnectClient.delete(file.getFullPath());
}
@Override
public String createDirectory(String baseDirectory, String newDirectoryName) throws Exception {
JSONObject postData = new JSONObject();
try {
postData.put("name", newDirectoryName);
} catch (JSONException e) {
e.printStackTrace();
return null;
}
LiveOperation operation = mSkyDriveConnectClient.post(baseDirectory, postData);
if (!operation.getResult().has(JsonKeys.ERROR)) {
return operation.getResult().getString(JsonKeys.ID);
}
return null;
}
public void deleteCurrentAccount() {
NetworkAccountDbAdapter.delete(mCurrentSkyDriveAccount.getId());
}
public List<FileProxy> getDirectoryFiles(String path) {
return getDirectoryFiles(path, null);
}
public List<FileProxy> getDirectoryFiles(String path, String parentPath) {
List<FileProxy> files = new ArrayList<>();
try {
LiveOperation operation = mSkyDriveConnectClient.get(isNullOrEmpty(path) || path.equals("/") ? "me/skydrive/files" : path + "/files");
JSONObject result = operation.getResult();
if (!result.isNull(JsonKeys.DATA)) {
JSONArray items = (JSONArray) result.get(JsonKeys.DATA);
for (int i = 0; i < items.length(); i++) {
JSONObject data = (JSONObject) items.get(i);
files.add(new SkyDriveFile(data, parentPath != null ? parentPath : path));
}
FileSystemScanner.sInstance.sort(files);
}
} catch (Exception e) {
throw NetworkException.handleNetworkException(e);
}
return files;
}
public FileProxy getFileInfo(String id) {
try {
LiveOperation operation = mSkyDriveConnectClient.get(id);
JSONObject result = operation.getResult();
return new SkyDriveFile(result, "");
} catch (Exception e) {
throw NetworkException.handleNetworkException(e);
}
}
@Override
public List<FileProxy> search(String path, String query) {
List<FileProxy> searchResult = new ArrayList<FileProxy>();
try {
LiveOperation liveOperation = mSkyDriveConnectClient.get("me/skydrive/search?q=" + query);
if (liveOperation != null) {
JSONObject result = liveOperation.getResult();
if (!result.isNull(JsonKeys.DATA)) {
JSONArray items = (JSONArray) result.get(JsonKeys.DATA);
for (int i = 0; i < items.length(); i++) {
JSONObject data = (JSONObject) items.get(i);
searchResult.add(new SkyDriveFile(data, path));
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return searchResult;
}
@Override
public boolean rename(FileProxy srcFile, String name) throws Exception {
JSONObject postData = new JSONObject();
name = name.substring(name.lastIndexOf("/") + 1, name.length());
try {
postData.put("name", name);
} catch (JSONException e) {
e.printStackTrace();
return false;
}
LiveOperation operation = mSkyDriveConnectClient.put(srcFile.getFullPath(), postData);
return !operation.getResult().has(JsonKeys.ERROR);
}
public void download(FileProxy source, OutputStream outputStream) throws LiveOperationException, IOException, JSONException {
// get file url
LiveOperation operation = mSkyDriveConnectClient.get(source.getFullPath());
// download file (via input stream)
BufferedInputStream inputStream = new BufferedInputStream(new URL(operation.getResult().getString(JsonKeys.SOURCE)).openStream());
int len;
byte[] BUFFER = new byte[256 * 1024];
while ((len = inputStream.read(BUFFER)) > 0) {
outputStream.write(BUFFER, 0, len);
}
inputStream.close();
outputStream.close();
}
public void setAuthTokensToSession(SkyDriveAccount account, OnLoginListener onLoginListener, String defaultPath) {
mCurrentSkyDriveAccount = account;
SharedPreferences settings =
App.sInstance.getSharedPreferences(PreferencesConstants.FILE_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = settings.edit();
editor.putString(PreferencesConstants.REFRESH_TOKEN_KEY, account.getToken()).commit();
mOnLoginListener = onLoginListener;
mDriveDefaultPath = defaultPath;
mSkyDriveAuthClient.initialize(this);
}
public void startAuthentication(Activity activity, OnLoginListener onLoginListener) {
mOnLoginListener = onLoginListener;
mAuthActivity = activity;
mSkyDriveAuthClient.logout(null);
mSkyDriveAuthClient.login(mAuthActivity, Arrays.asList(SCOPES), this);
}
public LiveConnectClient getConnectClient() {
return mSkyDriveConnectClient;
}
public void onAuthComplete(LiveStatus status, final LiveConnectSession session, Object userState) {
if (status == LiveStatus.CONNECTED) {
mAuthActivity = null;
mSkyDriveConnectClient = new LiveConnectClient(session);
if (mCurrentSkyDriveAccount == null) {
mOnLoginListener.onGetUserInfo();
mSkyDriveConnectClient.getAsync("me", new LiveOperationListener() {
@Override
public void onError(LiveOperationException exception, LiveOperation operation) {
mOnLoginListener.onError(R.string.error_getting_account_info);
}
@Override
public void onComplete(LiveOperation operation) {
JSONObject result = operation.getResult();
if (result.has(JsonKeys.ERROR)) {
JSONObject error = result.optJSONObject(JsonKeys.ERROR);
mOnLoginListener.onError(R.string.error_getting_account_info);
} else {
JSONObject authData = new JSONObject();
try {
authData.put(SKYDRIVE_ACCESS_TOKEN, session.getAccessToken());
authData.put(SKYDRIVE_REFRESH_TOKEN, session.getRefreshToken());
NetworkAccountDbAdapter.insert(
result.optString("name") + "(" + result.optString("id") + ")",
NetworkEnum.SkyDrive.ordinal(), authData.toString());
mOnLoginListener.onComplete(mDriveDefaultPath);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
});
} else {
mOnLoginListener.onComplete(mDriveDefaultPath);
}
} else {
if (mCurrentSkyDriveAccount != null) {
mCurrentSkyDriveAccount = null;
mSkyDriveAuthClient.login(mAuthActivity, Arrays.asList(SCOPES), this);
} else {
mOnLoginListener.onError(R.string.error_common);
}
}
}
public void onAuthError(LiveAuthException exception, Object userState) {
mSkyDriveConnectClient = null;
if ("invalid_grant".equals(exception.getError())) {
mOnLoginListener.onError(R.string.error_account_expired);
} else {
mOnLoginListener.onError(R.string.error_common);
}
}
public static class SkyDriveAccount extends NetworkAccount {
private String mToken;
public SkyDriveAccount(long id, String userName, JSONObject data) throws JSONException {
this(id, userName, data.getString(SKYDRIVE_REFRESH_TOKEN));
}
public SkyDriveAccount(long id, String userName, String token) {
mId = id;
mUserName = userName;
mToken = token;
}
public String getToken() {
return mToken;
}
@Override
public NetworkEnum getNetworkType() {
return NetworkEnum.SkyDrive;
}
}
public static interface OnLoginListener {
public void onGetUserInfo();
public void onComplete(String defaultPath);
public void onError(int errorCode);
}
}