package org.redcross.openmapkit.tagswipe;
import android.view.View;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import com.spatialdev.osm.model.OSMElement;
import org.redcross.openmapkit.Constraints;
import org.redcross.openmapkit.odkcollect.ODKCollectData;
import org.redcross.openmapkit.odkcollect.ODKCollectHandler;
import org.redcross.openmapkit.odkcollect.tag.ODKTag;
import org.redcross.openmapkit.odkcollect.tag.ODKTagItem;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Created by Nicholas Hallahan on 3/4/15.
* nhallahan@spatialdev.com
* * *
*/
public class TagEdit {
private static LinkedHashMap<String, TagEdit> tagEditHash;
private static LinkedHashMap<String, TagEdit> tagEditHiddenHash;
private static List<TagEdit> tagEdits;
private static OSMElement osmElement;
private static TagSwipeActivity tagSwipeActivity;
private final String tagKey; // a given TagEdit always associates to an immutable key
private String tagVal;
private ODKTag odkTag;
private boolean readOnly;
private boolean checkBoxMode = false;
private EditText editText;
private RadioGroup radioGroup;
/**
* For CheckBox mode.
*/
private CheckBox editTextCheckBox;
private EditText checkBoxEditText;
/**
* Factory Method that gives collection of instances.
*
* @return
*/
public static List<TagEdit> buildTagEdits() {
tagEditHash = new LinkedHashMap<>();
tagEditHiddenHash = new LinkedHashMap<>();
tagEdits = new ArrayList<>();
osmElement = OSMElement.getSelectedElements().getFirst();
Map<String, String> tags = osmElement.getTags();
// Tag Edits for ODK Collect Mode
if (ODKCollectHandler.isODKCollectMode()) {
Map<String, String> readOnlyTags = new HashMap<>(tags);
ODKCollectData odkCollectData = ODKCollectHandler.getODKCollectData();
Collection<ODKTag> requiredTags = odkCollectData.getRequiredTags();
for (ODKTag odkTag : requiredTags) {
String tagKey = odkTag.getKey();
TagEdit tagEdit = new TagEdit(tagKey, tagValueOrDefaultValue(tags, tagKey), odkTag, false);
String implicitVal = Constraints.singleton().implicitVal(tagKey);
if (implicitVal != null) {
tagEditHiddenHash.put(tagKey, tagEdit);
osmElement.addOrEditTag(tagKey, implicitVal);
} else if (Constraints.singleton().tagShouldBeShown(tagKey, osmElement)) {
tagEditHash.put(tagKey, tagEdit);
tagEdits.add(tagEdit);
} else {
tagEditHiddenHash.put(tagKey, tagEdit);
}
readOnlyTags.remove(tagKey);
}
Set<String> readOnlyKeys = readOnlyTags.keySet();
for (String readOnlyKey : readOnlyKeys) {
TagEdit tagEdit = new TagEdit(readOnlyKey, readOnlyTags.get(readOnlyKey), true);
tagEditHash.put(readOnlyKey, tagEdit);
tagEdits.add(tagEdit);
}
}
// Tag Edits for Standalone Mode
else {
Set<String> keys = tags.keySet();
for (String key : keys) {
TagEdit tagEdit = new TagEdit(key, tags.get(key), false);
tagEditHash.put(key, tagEdit);
tagEdits.add(tagEdit);
}
}
return tagEdits;
}
private static String tagValueOrDefaultValue(Map<String,String> tags, String tagKey) {
String tagVal = tags.get(tagKey);
if (tagVal == null) {
// null if there is no default
tagVal = Constraints.singleton().tagDefaultValue(tagKey);
if (tagVal != null) {
osmElement.addOrEditTag(tagKey, tagVal);
}
}
return tagVal;
}
public static void setTagSwipeActivity(TagSwipeActivity tagSwipeActivity) {
TagEdit.tagSwipeActivity = tagSwipeActivity;
}
public static TagEdit getTag(int idx) {
return tagEdits.get(idx);
}
public static TagEdit getTag(String key) {
return tagEditHash.get(key);
}
public static Set<String> hiddenTagKeys() {
return tagEditHash.keySet();
}
public static Set<String> shownTagKeys() {
return tagEditHiddenHash.keySet();
}
public static int getIndexForTagKey(String key) {
TagEdit tagEdit = tagEditHash.get(key);
if (tagEdit != null) {
return tagEdits.indexOf(tagEdit);
}
// If its not there, just go to the first TagEdit
return 0;
}
public static boolean saveToODKCollect(String osmUserName) {
updateTagsInOSMElement();
Set<String> missingTags = Constraints.singleton().requiredTagsNotMet(osmElement);
if (missingTags.size() > 0) {
tagSwipeActivity.notifyMissingTags(missingTags);
return false;
} else {
ODKCollectHandler.saveXmlInODKCollect(osmElement, osmUserName);
return true;
}
}
private static void removeTag(String key, String activeTagKey) {
if (tagEditHash.get(key) == null) return;
int idx = getIndexForTagKey(key);
TagEdit tagEdit = tagEditHash.remove(key);
tagEditHiddenHash.put(key, tagEdit);
tagEdits.remove(idx);
if (tagSwipeActivity != null) {
tagSwipeActivity.updateUI(activeTagKey);
}
}
private static void addTag(String key, String activeTagKey) {
if (tagEditHiddenHash.get(key) == null) return;
int idx = getIndexForTagKey(activeTagKey) + 1;
TagEdit tagEdit = tagEditHiddenHash.remove(key);
tagEditHash.put(key, tagEdit);
tagEdits.add(idx, tagEdit);
if (tagSwipeActivity != null) {
tagSwipeActivity.updateUI(activeTagKey);
}
}
private static void updateTagsInOSMElement() {
for (TagEdit tagEdit : tagEdits) {
tagEdit.updateTagInOSMElement();
}
}
private TagEdit(String tagKey, String tagVal, ODKTag odkTag, boolean readOnly) {
this.tagKey = tagKey;
this.tagVal = tagVal;
this.odkTag = odkTag;
this.readOnly = readOnly;
}
private TagEdit(String tagKey, String tagVal, boolean readOnly) {
this.tagKey = tagKey;
this.tagVal = tagVal;
this.readOnly = readOnly;
}
/**
* The EditText widget from StringTagValueFragment gets passed into here
* so that the value can be retrieved on save.
* * * *
* @param editText
*/
public void setEditText(EditText editText) {
this.editText = editText;
}
public void setRadioGroup(RadioGroup radioGroup) {
this.radioGroup = radioGroup;
}
public void setupEditCheckbox(CheckBox cb, EditText et) {
checkBoxMode = true;
editTextCheckBox = cb;
checkBoxEditText = et;
}
public ODKTag getODKTag() {
return odkTag;
}
public void updateTagInOSMElement() {
// check boxes
if (odkTag != null && checkBoxMode) {
boolean editTextCheckBoxChecked = editTextCheckBox.isChecked();
if (odkTag.hasCheckedTagValues() || editTextCheckBoxChecked) {
if (editTextCheckBoxChecked) {
tagVal = odkTag.getSemiColonDelimitedTagValues(checkBoxEditText.getText().toString());
} else {
tagVal = odkTag.getSemiColonDelimitedTagValues(null);
}
addOrEditTag(tagKey, tagVal);
} else {
deleteTag(tagKey);
}
return;
}
// radio buttons
if (radioGroup != null && odkTag != null) {
View v = radioGroup.getChildAt(radioGroup.getChildCount() - 1);
int checkedId = radioGroup.getCheckedRadioButtonId();
// has custom value input
if (v instanceof LinearLayout) {
LinearLayout customLL = (LinearLayout)v;
RadioButton customRadio = (RadioButton)customLL.getChildAt(0);
if (customRadio.isChecked()) {
EditText et = (EditText)customLL.getChildAt(1);
tagVal = et.getText().toString();
addOrEditTag(tagKey, tagVal);
} else if (checkedId != -1) {
tagVal = odkTag.getTagItemValueFromButtonId(checkedId);
addOrEditTag(tagKey, tagVal);
} else {
deleteTag(tagKey);
}
}
// no custom value input
else {
if (checkedId != -1) {
tagVal = odkTag.getTagItemValueFromButtonId(checkedId);
addOrEditTag(tagKey, tagVal);
} else {
deleteTag(tagKey);
}
}
}
// edit text
else if (editText != null) {
tagVal = editText.getText().toString();
addOrEditTag(tagKey, tagVal);
}
}
private void addOrEditTag(String tagKey, String tagVal) {
osmElement.addOrEditTag(tagKey, tagVal);
Constraints.TagAction tagAction = Constraints.singleton().tagAddedOrEdited(tagKey, tagVal);
executeTagAction(tagAction);
}
private void deleteTag(String tagKey) {
osmElement.deleteTag(tagKey);
tagVal = null;
Constraints.TagAction tagAction = Constraints.singleton().tagDeleted(tagKey);
executeTagAction(tagAction);
}
private void executeTagAction(Constraints.TagAction tagAction) {
for (String tag : tagAction.hide) {
removeTag(tag, tagKey);
}
for (String tag : tagAction.show) {
addTag(tag, tagKey);
}
}
public String getTitle() {
return tagKey;
}
public String getTagKeyLabel() {
if (odkTag != null) {
return odkTag.getLabel();
}
return null;
}
public String getTagKey() {
return tagKey;
}
public String getTagValLabel() {
if (odkTag == null) return null;
ODKTagItem item = odkTag.getItem(tagVal);
if (item != null) {
return item.getLabel();
}
return null;
}
public String getTagVal() {
return tagVal;
}
public Set<String> getTagVals() {
Set<String> tagVals = new HashSet<>();
if (tagVal == null || tagVal.length() < 1) {
return tagVals;
}
String[] vals = tagVal.trim().split(";");
for (int i = 0; i < vals.length; i++) {
String val = vals[i];
tagVals.add(val);
}
return tagVals;
}
public boolean isReadOnly() {
return readOnly;
}
public boolean isSelectOne() {
return !readOnly &&
odkTag != null &&
odkTag.getItems().size() > 0 &&
!Constraints.singleton().tagIsSelectMultiple(odkTag.getKey());
}
public boolean isSelectMultiple() {
return !readOnly &&
odkTag != null &&
odkTag.getItems().size() > 0 &&
Constraints.singleton().tagIsSelectMultiple(odkTag.getKey());
}
}