package pk.contender.earmouse;
import android.app.Activity;
import android.app.Fragment;
import android.content.Context;
import android.content.SharedPreferences;
import android.net.http.AndroidHttpClient;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.message.BasicHttpRequest;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* Implements a detailed view and installation option of user-selected Module in {@link pk.contender.earmouse.ModuleManagerActivity}
*
* @author Paul Klinkenberg <pklinken.development@gmail.com>
*/
public class ManagerDetailsFragment extends Fragment {
/* SharedPreferences constants */
private static final String PREFERENCES_MANAGERDETAILSFRAGMENT_ID = "preferences_ManagerDetailsFragment_id";
private Context mCtx;
/** The user-selected Module */
private Module mod = null;
/** ID of the selected Module, used for fetching and storing
* @see Module#id */
private int id = -1;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_managerdetail, container, false);
mCtx = getActivity();
if(mCtx == null)
Log.d("DEBUG", "Context is null in ManagerDetailsFragment onCreate()");
return view;
}
/**
* Restore fragment state.
*/
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if(getActivity().getClass() != ManagerDetailActivity.class)
{ // When running on a tablet restore the saved ID, on a handheld the activity will be reconstructed from the Intent.
SharedPreferences settings = mCtx.getSharedPreferences(Main.PREFS_NAME, Activity.MODE_PRIVATE);
id = settings.getInt(PREFERENCES_MANAGERDETAILSFRAGMENT_ID, -1);
// TODO: Would refetch a loaded module on screen rotate when saving the state would be sufficient.
update();
}
}
/**
* Save fragment state.
*/
@Override
public void onPause() {
super.onPause();
SharedPreferences settings = mCtx.getSharedPreferences(Main.PREFS_NAME, Activity.MODE_PRIVATE);
settings.edit().putInt(PREFERENCES_MANAGERDETAILSFRAGMENT_ID, id).apply();
}
void setId(int id) {
this.id = id;
}
/**
* Update UI, either sets the UI to the empty UI or fetches the selected Module from the server.
*/
void update() {
if(id < 0) {
setEmpty();
} else {
new FetchModuleJsonFromServer().execute();
}
}
/**
* Installs the selected Module. After installation displays a Toast message and tells {@link pk.contender.earmouse.ModuleManagerActivity}
* to update itself.
* @param view The View that received the click event
*/
public void onButtonClick(@SuppressWarnings("UnusedParameters") View view) {
if(mod != null){
// User request to install this module
if(mod.writeModuleToJson()) {
Toast toast = Toast.makeText(mCtx, mCtx.getString(R.string.toast_module_installed), Toast.LENGTH_LONG);
toast.show();
// FIXME: Should check for null here, apparently static isn't so holy.
for(Module mod : ModuleManagerActivity.shownModuleList) {
if(mod.getId() == id) {
ModuleManagerActivity.mAdapter.remove(mod);
ModuleManagerActivity.mAdapter.notifyDataSetChanged();
break;
}
}
mod = null;
id = -1;
//update();
} else {
Toast toast = Toast.makeText(mCtx, mCtx.getString(R.string.toast_error_installing_module), Toast.LENGTH_LONG);
toast.show();
}
}
}
/**
* Set the UI to only display a 'no module selected' message
*/
void setEmpty() {
TextView titleView = (TextView) getActivity().findViewById(R.id.module_title);
TextView descriptionView = (TextView) getActivity().findViewById(R.id.module_description);
View divider = getActivity().findViewById(R.id.button_divider);
Button button = (Button) getActivity().findViewById(R.id.manager_button);
TextView messageView = (TextView) getActivity().findViewById(R.id.message_text);
if(titleView != null) {
titleView.setText("");
titleView.setVisibility(View.GONE);
}
if(descriptionView != null) {
descriptionView.setText("");
descriptionView.setVisibility(View.GONE);
}
if(divider != null) {
divider.setVisibility(View.GONE);
}
if(button != null) {
button.setText("");
button.setVisibility(View.GONE);
}
if(messageView != null)
messageView.setVisibility(View.VISIBLE);
mod = null;
}
/**
* Set the UI to display the standard layout.
*/
void setNotEmpty() {
TextView titleView = (TextView) getActivity().findViewById(R.id.module_title);
TextView descriptionView = (TextView) getActivity().findViewById(R.id.module_description);
View divider = getActivity().findViewById(R.id.button_divider);
Button button = (Button) getActivity().findViewById(R.id.manager_button);
TextView messageView = (TextView) getActivity().findViewById(R.id.message_text);
if(titleView != null) {
titleView.setText("");
titleView.setVisibility(View.VISIBLE);
}
if(descriptionView != null) {
descriptionView.setText("");
descriptionView.setVisibility(View.VISIBLE);
}
if(divider != null) {
divider.setVisibility(View.VISIBLE);
}
if(button != null) {
button.setText("");
button.setVisibility(View.VISIBLE);
}
if(messageView != null)
messageView.setVisibility(View.GONE);
}
/**
* Contacts a remote host, fetches the Module JSON for {@link ManagerDetailsFragment#id},
* loads its data and sets up the UI.
*/
private class FetchModuleJsonFromServer extends AsyncTask<Void, Void, Module> {
private AndroidHttpClient httpClient = null;
private Context mCtx;
@Override
protected void onPostExecute(Module result) {
if(httpClient != null)
httpClient.close();
if(result == null) {
Toast toast = Toast.makeText(mCtx, mCtx.getResources().getText(R.string.http_received_empty), Toast.LENGTH_LONG);
toast.show();
return;
}
mod = result;
setNotEmpty();
Activity callingActivity = getActivity();
if(callingActivity != null) {
// Can't use mCtx here as Activity may be destroyed once we reach this point
TextView titleView = (TextView) callingActivity.findViewById(R.id.module_title);
TextView descriptionView = (TextView) callingActivity.findViewById(R.id.module_description);
if (titleView != null)
titleView.setText(mod.getTitle());
if (descriptionView != null)
descriptionView.setText(mod.getDescription());
Button button = (Button) callingActivity.findViewById(R.id.manager_button);
if (button != null) {
button.setText(callingActivity.getResources().getText(R.string.manager_install_button));
} else
Log.d("DEBUG", "Button is null");
} else
Log.d("DEBUG", "callingActivity is null in onPostExecute in FetchModuleJsonFromServer");
}
@Override
protected void onCancelled(Module result) {
// Task was cancelled so we cannot display the module, end activity and display a Toast message
if(httpClient != null)
httpClient.close();
Activity callingActivity = getActivity();
if(callingActivity != null) {
// Can't use mCtx here as Activity may be destroyed once we reach this point
Toast toast = Toast.makeText(callingActivity, mCtx.getResources().getText(R.string.http_error), Toast.LENGTH_LONG);
toast.show();
id = -1;
setEmpty();
}
}
// TODO: Set up a progressbar to display while contacting a server.
@Override
protected Module doInBackground(Void... params) {
httpClient = AndroidHttpClient.newInstance("Earmouse/" + Main.VERSION);
HttpHost host = new HttpHost(Main.SERVER_HOST, Main.SERVER_PORT);
String localizedModulePath = Main.SERVER_PATH + "module" + Main.getLocaleSuffix() +
"_" + id + ".json";
BasicHttpRequest request = new BasicHttpRequest("GET", localizedModulePath);
HttpResponse response;
try {
response = httpClient.execute(host, request);
} catch (IOException e) {
e.printStackTrace();
cancel(false);
return null;
}
HttpEntity entity;
if(response != null) {
entity = response.getEntity();
} else {
cancel(false);
return null;
}
if(entity != null) {
Log.d("DEBUG", "entity.getContentLength() returns " + entity.getContentLength());
} else {
cancel(false);
return null;
}
InputStreamReader reader;
try {
reader = new InputStreamReader(entity.getContent());
} catch (IllegalStateException | IOException e) {
e.printStackTrace();
cancel(false);
return null;
}
Module result = new Module(mCtx, reader);
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
@Override
protected void onPreExecute() {
mCtx = getActivity();
}
}
}