package org.azavea.otm.ui;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.Toast;
import org.azavea.helpers.Logger;
import org.azavea.otm.Choice;
import org.azavea.otm.R;
import org.azavea.otm.data.UDFCollectionDefinition;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import static com.google.common.collect.Collections2.transform;
import static com.google.common.collect.Iterables.getLast;
import static com.google.common.collect.Lists.newArrayList;
public abstract class UDFCollectionActivity extends Activity {
public static final String UDF_DEFINITIONS = "udfs";
protected JSONObject value;
private String collectionKey;
private Fragment currentFragment = null;
private UDFKeyChoiceFragment fieldChoiceFragment;
private List<Fragment> fieldFragments;
// Index into subFieldDefinitions, set to -1 so the first +1 puts us at the start of fieldFragments
private int currentFragmentIndex = -1;
private Map<String, UDFCollectionDefinition> udfDefinitions;
private MenuItem nextButton;
public abstract List<JSONObject> getFieldTypes(UDFCollectionDefinition udfDef);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.collection_udf_add_activity);
final List<UDFCollectionDefinition> udfDefinitions = getIntent().getParcelableArrayListExtra(UDF_DEFINITIONS);
final ArrayList<Choice> choices = newArrayList(
transform(udfDefinitions, u -> new Choice(u.getLabel(), u.getCollectionKey())));
this.udfDefinitions = groupUdfDefinitionsByKey(udfDefinitions);
// Only show the screen to select the UDF type if there is more than 1
if (udfDefinitions.size() == 1) {
setUDF(udfDefinitions.get(0));
setCurrentFragment(0);
} else {
fieldChoiceFragment = UDFKeyChoiceFragment.newInstance(choices);
setFieldChoiceFragment();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.udf_create_menu, menu);
// We need a handle on the next button to enable/disable it
nextButton = menu.findItem(R.id.udf_create_next_button);
if (fieldFragments != null && fieldFragments.size() == 1) {
nextButton.setTitle(R.string.udf_create_done_text);
}
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.udf_create_next_button) {
if (currentFragmentIndex + 1 < fieldFragments.size()) {
setCurrentFragment(currentFragmentIndex + 1);
} else {
Intent result = new Intent();
addArgumentsToResult(result);
setResult(RESULT_OK, result);
finish();
}
return true;
}
return super.onOptionsItemSelected(item);
}
protected void addArgumentsToResult(Intent result) {
result.putExtra(collectionKey, value.toString());
}
@Override
public void onBackPressed() {
if (currentFragmentIndex < 0) {
super.onBackPressed();
} else {
setCurrentFragment(currentFragmentIndex - 1);
}
}
/**
* Set the currently selected collection UDF.
* This will reset all stored state if a different collection UDF had already been selected
*
* @param collectionKey the key of the collection UDF
*/
public void onUDFFieldSelected(String collectionKey) {
if (this.collectionKey == null || !this.collectionKey.equals(collectionKey)) {
final UDFCollectionDefinition newUDFDef = udfDefinitions.get(collectionKey);
setUDF(newUDFDef);
}
nextButton.setEnabled(true);
}
protected void setUDF(UDFCollectionDefinition currentUDFDef) {
this.collectionKey = currentUDFDef.getCollectionKey();
this.value = new JSONObject();
this.fieldFragments = getFieldFragments(currentUDFDef);
}
/**
* Set the value of the specified UDF sub-field
*
* @param fieldName the field name to set a value for
* @param value the value to save
*/
public void onValueChanged(String fieldName, String value) {
try {
this.value.put(fieldName, value);
nextButton.setEnabled(true);
} catch (JSONException e) {
Logger.error(e);
Toast.makeText(this, R.string.udf_create_error_saving, Toast.LENGTH_SHORT).show();
}
}
public void setActionBarTitle(String title) {
getActionBar().setTitle(title);
}
private void setCurrentFragment(int fieldNumber) {
this.currentFragmentIndex = fieldNumber;
if (fieldNumber < 0 && fieldChoiceFragment == null) {
// If there is no UDF choice screen, go back to the tree edit screen
super.onBackPressed();
} else if (fieldNumber < 0) {
setFieldChoiceFragment();
} else if (fieldNumber < fieldFragments.size()) {
setFragment(fieldFragments.get(fieldNumber));
if (nextButton != null) {
if (fieldNumber == fieldFragments.size() - 1) {
nextButton.setTitle(R.string.udf_create_done_text);
} else {
nextButton.setTitle(R.string.udf_create_next_button_text);
}
}
} else {
Logger.error("Fragment requested, but there was none to show...");
}
}
private void setFieldChoiceFragment() {
// The collection UDFs in a group usually have the same name, so just use the last one
final String title = getLast(udfDefinitions.values()).getDisplayName();
setActionBarTitle(title);
setFragment(fieldChoiceFragment);
}
private void setFragment(Fragment fragment) {
FragmentTransaction ft = getFragmentManager().beginTransaction();
if (currentFragment != null) {
ft.hide(currentFragment);
}
currentFragment = fragment;
if (fragment.isHidden()) {
ft.show(fragment);
} else {
ft.add(R.id.fragment_container, fragment);
}
ft.commit();
if (nextButton != null) {
nextButton.setEnabled(false);
}
}
private List<Fragment> getFieldFragments(UDFCollectionDefinition udfDef) {
final List<JSONObject> fieldDefs = getFieldTypes(udfDef);
final List<Fragment> fragments = new ArrayList<>();
for (JSONObject subFieldDef : fieldDefs) {
final String type = subFieldDef.optString("type");
if ("choice".equals(type)) {
fragments.add(UDFSubFieldChoiceFragment.newInstance(subFieldDef));
} else if ("date".equals(type)) {
fragments.add(UDFDateFragment.newInstance(subFieldDef));
} else {
Logger.warning("Unsupported Collection UDF field type " + type);
}
}
return fragments;
}
private static LinkedHashMap<String, UDFCollectionDefinition> groupUdfDefinitionsByKey(Collection<UDFCollectionDefinition> udfDefs) {
final LinkedHashMap<String, UDFCollectionDefinition> udfDefMap = new LinkedHashMap<>(udfDefs.size());
for (UDFCollectionDefinition udfDef : udfDefs) {
final String udfDefKey = udfDef.getCollectionKey();
udfDefMap.put(udfDefKey, udfDef);
}
return udfDefMap;
}
}