package com.llamacorp.equate.unit;
import android.content.Context;
import android.content.res.Resources;
import com.llamacorp.equate.ResourceArrayParser;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;
/**
* Class to store and manage the array of Unit Types available to the calculator
*/
public class UnitTypeList {
private static final String JSON_UNIT_TYPE_MAP = "unit_type_map";
private static final String JSON_UNIT_TYPE_ORDER = "unit_type_order";
private static final String JSON_UNIT_TYPE = "unit_type";
private static final int DEFAULT_POS = 3;
private final ArrayList<String> XML_KEYS;
private final ArrayList<String> TAB_NAMES;
//actually stores all of the Unit Type Objects
private HashMap<String, UnitType> mUnits;
private ArrayList<String> mOrderedUnitKeys;
//stores the current location in mUnitTypeArray
private String mCurrentKey;
public UnitTypeList(Resources resources) {
XML_KEYS = ResourceArrayParser.getUnitTypeKeyArrayList(resources);
TAB_NAMES = ResourceArrayParser.getUnitTypeTabNameArrayList(resources);
//initialize storage members
mUnits = new HashMap<>();
mOrderedUnitKeys = new ArrayList<>();
//clear existing values and load in defaults
initialize();
}
/**
* Constructor used to build a new UnitTypeList with a JSON object. This is
* used to recall saved Unit Type Arrays that might have different visibility,
* order, or unit customizations from the user.
*
* @param json Object to load JSON from
* @throws JSONException
*/
public UnitTypeList(Resources resources, JSONObject json) throws JSONException {
this(resources); // initialize unit array
JSONArray jUnitTypeArray = json.getJSONArray(JSON_UNIT_TYPE_MAP);
//if we added another UnitType and total count is different than previous
// just use default
if (jUnitTypeArray.length() == mUnits.size()){
//Load in user settings to already assembled UnitType array
int i = 0;
for (String key : mUnits.keySet()) {
mUnits.get(key).loadJSON(jUnitTypeArray.getJSONObject(i));
i++;
}
//load out the array or keys that define the desired order
JSONArray jUnitOrderArray = json.getJSONArray(JSON_UNIT_TYPE_ORDER);
ArrayList<String> temp = new ArrayList<>();
for (int k = 0; k < jUnitOrderArray.length(); k++) {
temp.add(jUnitOrderArray.getString(k));
}
mOrderedUnitKeys = temp;
//grab the current key
mCurrentKey = json.getString(JSON_UNIT_TYPE);
}
}
/**
* Loads the Unit Type Array into a JSON array for use in parent class for
* saving customizations.
*
* @return JSON array of Unit Types
* @throws JSONException
*/
public JSONObject toJSON() {
JSONObject jsonReturnObj = new JSONObject();
try {
jsonReturnObj.put(JSON_UNIT_TYPE, getCurrentKey());
} catch (JSONException e) {
e.printStackTrace();
}
JSONArray jUnitTypeArray = new JSONArray();
for (UnitType u : mUnits.values())
try {
jUnitTypeArray.put(u.toJSON());
} catch (JSONException e) {
e.printStackTrace();
}
try {
jsonReturnObj.put(JSON_UNIT_TYPE_MAP, jUnitTypeArray);
} catch (JSONException e) {
e.printStackTrace();
}
JSONArray jOrderedKeyArray = new JSONArray();
for (String s : mOrderedUnitKeys)
jOrderedKeyArray.put(s);
try {
jsonReturnObj.put(JSON_UNIT_TYPE_ORDER, jOrderedKeyArray);
} catch (JSONException e) {
e.printStackTrace();
}
return jsonReturnObj;
}
/**
* Helper method used to initiate the array of various types of units
*/
public void initialize() {
//set the unit type to length by default
if (DEFAULT_POS < XML_KEYS.size())
mCurrentKey = XML_KEYS.get(DEFAULT_POS);
else
mCurrentKey = XML_KEYS.get(0);
mUnits.clear();
mUnits = UnitInitializer.getUnitTypeMap(XML_KEYS, TAB_NAMES);
mOrderedUnitKeys.clear();
mOrderedUnitKeys = new ArrayList<>(XML_KEYS);
}
/**
* Gets the key of the currency selected Unit Type
*/
public String getCurrentKey() {
return mCurrentKey;
}
/**
* Get the Unit Type at the given key.
* @param key of Unit Type to get
*/
public UnitType get(String key){
return mUnits.get(key);
}
/**
* Get the Unit Type at the given index of the currently visible Unit Types
* @param index of the visible Unit Type to get
*/
public UnitType get(int index){
return mUnits.get(mOrderedUnitKeys.get(index));
}
public HashMap<String, UnitType> getUnitTypeArray() {
return mUnits;
}
/**
* Get the currently selected Unit Type
*/
public UnitType getCurrent() {
return get(getCurrentKey());
}
/**
* Set the currently selected Unit Type
*/
public void setCurrent(String key) {
mCurrentKey = key;
}
/**
* Set the currently selected Unit Type by index of currently visible Unit
* Types
*/
public void setCurrent(int index) {
mCurrentKey = mOrderedUnitKeys.get(index);
}
public int numberVisible() {
return mOrderedUnitKeys.size();
}
public int getIndex(String key) {
return mOrderedUnitKeys.indexOf(key);
}
/**
* Gets the index of the currently selected unit within the visible and
* ordered Unit Types
*/
public int getCurrentIndex() {
int index = getIndex(getCurrentKey());
// // we have some error with the current key, default to 0
// if (index == -1) {
// setCurrent(0);
// index = 0;
// }
return index;
}
/**
* Update values of units that are not static (currency) via
* each unit's own HTTP/JSON API call. Note that this refresh
* is asynchronous and will only happen sometime in the future
* Internet connection permitting.
*
* @param forced should update be forced without waiting for time-out
*/
public void refreshDynamicUnits(Context context, boolean forced) {
for (UnitType ut : mUnits.values())
ut.refreshDynamicUnits(context, forced);
}
public void setOrdered(Set<String> ordered) {
if (ordered == null){
mOrderedUnitKeys.clear();
mOrderedUnitKeys = new ArrayList<>(XML_KEYS);
} else {
mOrderedUnitKeys = new ArrayList<>(XML_KEYS);
mOrderedUnitKeys.retainAll(ordered);
}
}
}