package com.door43.translationstudio.newui.home;
import android.app.DialogFragment;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.support.design.widget.Snackbar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import com.door43.tools.reporting.Logger;
import com.door43.translationstudio.AppContext;
import com.door43.translationstudio.R;
import com.door43.translationstudio.core.Profile;
import com.door43.translationstudio.core.TargetTranslation;
import com.door43.translationstudio.core.TargetTranslationMigrator;
import com.door43.translationstudio.core.Translator;
import com.door43.translationstudio.dialogs.CustomAlertDialog;
import com.door43.translationstudio.tasks.AdvancedGogsRepoSearchTask;
import com.door43.translationstudio.tasks.CloneRepositoryTask;
import com.door43.translationstudio.tasks.RegisterSSHKeysTask;
import com.door43.translationstudio.tasks.SearchGogsRepositoriesTask;
import com.door43.translationstudio.tasks.SearchGogsUsersTask;
import com.door43.util.tasks.GenericTaskWatcher;
import com.door43.util.tasks.ManagedTask;
import com.door43.util.tasks.TaskManager;
import com.door43.widget.ViewUtil;
import org.apache.commons.io.FileUtils;
import org.json.JSONException;
import org.json.JSONObject;
import org.unfoldingword.gogsclient.Repository;
import org.unfoldingword.gogsclient.User;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* Created by joel on 5/10/16.
*/
public class ImportFromDoor43Dialog extends DialogFragment implements GenericTaskWatcher.OnFinishedListener {
private static final String STATE_REPOSITORIES = "state_repositories";
private GenericTaskWatcher taskWatcher;
private RestoreFromCloudAdapter adapter;
private Translator translator;
private List<Repository> repositories = new ArrayList<>();
private String cloneHtmlUrl;
private File cloneDestDir;
private EditText repoEditText;
private EditText userEditText;
public View onCreateView(LayoutInflater inflater, ViewGroup container, final Bundle savedInstanceState) {
getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);
View v = inflater.inflate(R.layout.dialog_import_from_door43, container, false);
this.taskWatcher = new GenericTaskWatcher(getActivity(), R.string.loading);
this.taskWatcher.setOnFinishedListener(this);
this.translator = AppContext.getTranslator();
Button dismissButton = (Button) v.findViewById(R.id.dismiss_button);
dismissButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
taskWatcher.stop();
SearchGogsRepositoriesTask task = (SearchGogsRepositoriesTask) TaskManager.getTask(SearchGogsRepositoriesTask.TASK_ID);
if (task != null) {
task.stop();
TaskManager.cancelTask(task);
TaskManager.clearTask(task);
}
dismiss();
}
});
userEditText = (EditText)v.findViewById(R.id.username);
repoEditText = (EditText)v.findViewById(R.id.translation_id);
v.findViewById(R.id.search_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String userQuery = userEditText.getText().toString();
String repoQuery = repoEditText.getText().toString();
AppContext.closeKeyboard(getActivity());
Profile profile = AppContext.getProfile();
if(profile != null && profile.gogsUser != null) {
AdvancedGogsRepoSearchTask task = new AdvancedGogsRepoSearchTask(profile.gogsUser, userQuery, repoQuery, 50);
TaskManager.addTask(task, AdvancedGogsRepoSearchTask.TASK_ID);
taskWatcher.watch(task);
} else {
AppContext.context().showToastMessage(R.string.login_doo43);
dismiss();
}
}
});
ListView list = (ListView) v.findViewById(R.id.list);
adapter = new RestoreFromCloudAdapter();
list.setAdapter(adapter);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Repository repo = adapter.getItem(position);
String repoName = repo.getFullName().replace("/", "-");
cloneDestDir = new File(AppContext.context().getCacheDir(), repoName + System.currentTimeMillis() + "/");
cloneHtmlUrl = repo.getHtmlUrl();
CloneRepositoryTask task = new CloneRepositoryTask(cloneHtmlUrl, cloneDestDir);
taskWatcher.watch(task);
TaskManager.addTask(task, CloneRepositoryTask.TASK_ID);
}
});
// restore state
if(savedInstanceState != null) {
String[] repoJsonArray = savedInstanceState.getStringArray(STATE_REPOSITORIES);
if(repoJsonArray != null) {
for (String json : repoJsonArray) {
try {
Repository repo = Repository.fromJSON(new JSONObject(json));
if (json != null) {
repositories.add(repo);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
adapter.setRepositories(repositories);
}
}
// connect to existing task
AdvancedGogsRepoSearchTask searchTask = (AdvancedGogsRepoSearchTask) TaskManager.getTask(AdvancedGogsRepoSearchTask.TASK_ID);
CloneRepositoryTask cloneTask = (CloneRepositoryTask) TaskManager.getTask(CloneRepositoryTask.TASK_ID);
if (searchTask != null) {
taskWatcher.watch(searchTask);
} else if (cloneTask != null) {
taskWatcher.watch(cloneTask);
}
return v;
}
@Override
public void onFinished(ManagedTask task) {
taskWatcher.stop();
TaskManager.clearTask(task);
if (task instanceof AdvancedGogsRepoSearchTask) {
this.repositories = ((AdvancedGogsRepoSearchTask) task).getRepositories();
adapter.setRepositories(repositories);
} else if (task instanceof CloneRepositoryTask) {
if (!task.isCanceled()) {
CloneRepositoryTask.Status status = ((CloneRepositoryTask)task).getStatus();
File tempPath = ((CloneRepositoryTask) task).getDestDir();
String cloneUrl = ((CloneRepositoryTask) task).getCloneUrl();
if(status == CloneRepositoryTask.Status.SUCCESS) {
Logger.i(this.getClass().getName(), "Repository cloned from " + cloneUrl);
tempPath = TargetTranslationMigrator.migrate(tempPath);
TargetTranslation tempTargetTranslation = TargetTranslation.open(tempPath);
boolean importFailed = false;
if (tempTargetTranslation != null) {
TargetTranslation existingTargetTranslation = translator.getTargetTranslation(tempTargetTranslation.getId());
if (existingTargetTranslation != null) {
// merge target translation
try {
existingTargetTranslation.merge(tempPath);
} catch (Exception e) {
Logger.e(this.getClass().getName(), "Failed to merge the target translation", e);
notifyImportFailed();
importFailed = true;
}
} else {
// restore the new target translation
try {
translator.restoreTargetTranslation(tempTargetTranslation);
} catch (IOException e) {
Logger.e(this.getClass().getName(), "Failed to import the target translation " + tempTargetTranslation.getId(), e);
notifyImportFailed();
importFailed = true;
}
}
} else {
Logger.e(this.getClass().getName(), "Failed to open the online backup");
notifyImportFailed();
importFailed = true;
}
FileUtils.deleteQuietly(tempPath);
if(!importFailed) {
Handler hand = new Handler(Looper.getMainLooper());
hand.post(new Runnable() {
@Override
public void run() {
// todo: terrible hack. We should instead register a listener with the dialog
((HomeActivity) getActivity()).notifyDatasetChanged();
Snackbar snack = Snackbar.make(ImportFromDoor43Dialog.this.getView(), R.string.success, Snackbar.LENGTH_SHORT);
ViewUtil.setSnackBarTextColor(snack, getResources().getColor(R.color.light_primary_text));
snack.show();
}
});
}
} else if(status == CloneRepositoryTask.Status.AUTH_FAILURE) {
Logger.i(this.getClass().getName(), "Authentication failed");
// if we have already tried ask the user if they would like to try again
if(AppContext.context().hasSSHKeys()) {
showAuthFailure();
return;
}
RegisterSSHKeysTask keyTask = new RegisterSSHKeysTask(false);
taskWatcher.watch(keyTask);
TaskManager.addTask(keyTask, RegisterSSHKeysTask.TASK_ID);
} else {
notifyImportFailed();
}
}
} else if(task instanceof RegisterSSHKeysTask) {
if(((RegisterSSHKeysTask)task).isSuccess()) {
Logger.i(this.getClass().getName(), "SSH keys were registered with the server");
// try to clone again
CloneRepositoryTask pullTask = new CloneRepositoryTask(cloneHtmlUrl, cloneDestDir);
taskWatcher.watch(pullTask);
TaskManager.addTask(pullTask, CloneRepositoryTask.TASK_ID);
} else {
notifyImportFailed();
}
}
}
public void showAuthFailure() {
CustomAlertDialog.Create(getActivity())
.setTitle(R.string.error).setMessage(R.string.auth_failure_retry)
.setPositiveButton(R.string.yes, new View.OnClickListener() {
@Override
public void onClick(View v) {
RegisterSSHKeysTask keyTask = new RegisterSSHKeysTask(true);
taskWatcher.watch(keyTask);
TaskManager.addTask(keyTask, RegisterSSHKeysTask.TASK_ID);
}
})
.setNegativeButton(R.string.no, new View.OnClickListener() {
@Override
public void onClick(View v) {
notifyImportFailed();
}
})
.show("auth-failed");
}
public void notifyImportFailed() {
CustomAlertDialog.Create(getActivity())
.setTitle(R.string.error)
.setMessage(R.string.restore_failed)
.setPositiveButton(R.string.dismiss, null)
.show("publish-failed");
}
@Override
public void onSaveInstanceState(Bundle out) {
List<String> repoJsonList = new ArrayList<>();
for (Repository r : repositories) {
repoJsonList.add(r.toJSON().toString());
}
out.putStringArray(STATE_REPOSITORIES, repoJsonList.toArray(new String[repoJsonList.size()]));
super.onSaveInstanceState(out);
}
@Override
public void onDestroy() {
taskWatcher.stop();
super.onDestroy();
}
}