package com.llamacorp.equate.view;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import com.llamacorp.equate.Calculator;
import com.llamacorp.equate.R;
import com.llamacorp.equate.unit.UnitHistCurrency;
import com.llamacorp.equate.unit.UnitType;
import com.llamacorp.equate.unit.UnitType.OnConvertKeyUpdateFinishedListener;
import java.util.ArrayList;
public class ConvKeysFragment extends Fragment implements OnConvertKeyUpdateFinishedListener {
//this is for communication with the parent activity
OnConvertKeySelectedListener mCallback;
// Container Activity must implement this interface
public interface OnConvertKeySelectedListener {
void updateScreen(boolean updateResult);
void setEqualButtonColor(boolean unitSet);
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
mCallback = (OnConvertKeySelectedListener) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString()
+ " must implement OnConvertKeySelectedListener");
}
}
//used for the extra
//TODO use getPackageName() instead
private static final String EXTRA_UNIT_TYPE_POS = "com.llamacorp.equate.unit_type_pos";
private static final int NUM_MORE_FAVORITES = 3;
private static final int NUM_UNITS_REQUIRED_FOR_FAVORITES = 25;
//holds UnitType for this fragment aka series of convert buttons
private UnitType mUnitType;
private ArrayList<Button> mConvButton;
private Button mMoreButton;
private int mNumConvButtons;
private int[] convertButtonIds = {
R.id.convert_button1,
R.id.convert_button2,
R.id.convert_button3,
R.id.convert_button4,
R.id.convert_button5,
R.id.convert_button6,
R.id.convert_button7,
R.id.convert_button8,
R.id.convert_button9,
R.id.convert_button10};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
int pos = getArguments().getInt(EXTRA_UNIT_TYPE_POS);
mUnitType = Calculator.getCalculator(getActivity()).getUnitType(pos);
mUnitType.setDynamicUnitCallback(this);
}
@Override
public void onResume() {
super.onResume();
colorSelectedButton();
}
public static ConvKeysFragment newInstance(int unitTypePos) {
Bundle args = new Bundle();
args.putInt(EXTRA_UNIT_TYPE_POS, unitTypePos);
ConvKeysFragment fragment = new ConvKeysFragment();
fragment.setArguments(args);
return fragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_convert_keys, parent, false);
mConvButton = new ArrayList<>();
mNumConvButtons = convertButtonIds.length;
//if we have more than 10 unit buttons, replace last convert button with a more button
if (mUnitType.size() > convertButtonIds.length){
mNumConvButtons = mNumConvButtons - 1;
mMoreButton = (Button) v.findViewById(convertButtonIds[mNumConvButtons]);
mMoreButton.setText(getText(R.string.more_button));
//button.setTypeface(null, Typeface.ITALIC);
mMoreButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
createMoreUnitsDialog(getText(R.string.select_unit),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int item) {
clickUnitButton(item + mNumConvButtons);
updateFavorites(item + mNumConvButtons);
}
});
}
});
}
for (int i = 0; i < mNumConvButtons; i++) {
Button button = (Button) v.findViewById(convertButtonIds[i]);
//add ellipses for long press
if (mUnitType.size() > mNumConvButtons)
((SecondaryTextButton) button).setSecondaryText((String) getText(R.string.ellipsis));
//add to our list of conv buttons
mConvButton.add(button);
//if button is empty, don't create OnClickListener for it
if (mUnitType.getUnitDisplayName(i).equals(""))
continue;
refreshButtonText(i);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int viewId = view.getId();
for (int i = 0; i < mNumConvButtons; i++) {
if (convertButtonIds[i] == viewId){
//select key
clickUnitButton(i);
//don't continue looking through the button array
break;
}
}
}
});
final int buttonPos = i;
button.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
//if there are less units to display than slots, move on
if (mUnitType.size() <= mNumConvButtons)
return true;
String title = getText(R.string.word_Change)
+ " " + mUnitType.getLowercaseGenericLongName(buttonPos)
+ " " + getText(R.string.word_to) + ":";
//pass the title and on item click listener
createMoreUnitsDialog(title, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int item) {
mUnitType.swapUnits(buttonPos, item + mNumConvButtons);
refreshButtonText(buttonPos);
}
});
return false;
}
});
}
return v;
}
/**
* Used by parent activity to select a unit within this fragment
*
* @param unitPos the position of Unit selected
*/
public void selectUnitAtUnitArrayPos(int unitPos) {
//unitPos will be -1 if it wasn't found
if (unitPos != -1 && mUnitType != null)
clickUnitButton(mUnitType.findButtonPositionforUnitArrayPos(unitPos));
}
/**
* Helper function to build a dialog box that list overflow units not shown
* on the screen. Dialog lists has a cancel button.
*
* @param title to display at top of dialog box
* @param itemClickListener OnClickListener for when the user selects one of the
* units in the dialog list
*/
private void createMoreUnitsDialog(CharSequence title, DialogInterface.OnClickListener itemClickListener) {
AlertDialog.Builder builder = new AlertDialog.
Builder(getActivity());
builder.setTitle(title);
builder.setItems(mUnitType.getUndisplayedUnitNames(mNumConvButtons), itemClickListener);
//null seems to do the same as canceling the dialog
builder.setPositiveButton(R.string.add_unit, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
createCustomUnitDialog();
}
});
builder.setNegativeButton(android.R.string.cancel, null);
AlertDialog alert = builder.create();
alert.show();
}
private void createCustomUnitDialog() {
AlertDialog.Builder builder = new AlertDialog.
Builder(getActivity());
builder.setTitle("Create Custom Unit:");
builder.setNegativeButton(android.R.string.cancel, null);
AlertDialog alert = builder.create();
alert.show();
}
public void refreshAllButtonsText() {
for (int i = 0; i < mConvButton.size(); i++) {
refreshButtonText(i);
}
}
private void refreshButtonText(int buttonPos) {
if (mUnitType.isUnitSelected()){
if (buttonPos != mUnitType.getCurrUnitButtonPos()){
refreshButtonText(getResources()
.getString(R.string.convert_arrow), buttonPos);
}
setSelectedButtonHighlight(true);
}
else {
refreshButtonText("", buttonPos);
}
}
private void refreshButtonText(String textPrefix, int buttonPos) {
//if trying to update historical curr text and button not on screen, move on
if (buttonPos >= mNumConvButtons)
return;
String displayText = mUnitType.getUnitDisplayName(buttonPos);
if (displayText.equals(""))
return;
displayText = textPrefix + displayText;
if (mUnitType.containsDynamicUnits() && mUnitType.isUpdating())
if (mUnitType.isUnitDynamic(buttonPos) && isAdded())
displayText = (String) getText(R.string.word_updating);
Button button = mConvButton.get(buttonPos);
button.setText(displayText);
//accent the text color of the button
button.setHovered(!textPrefix.equals(""));
//TODO crude method here, since this is called 10x times and only needs
//to be called once
if (mMoreButton != null)
mMoreButton.setHovered(!textPrefix.equals(""));
}
/**
* Used to pass selected unit to the UnitType model class
*
* @param buttonPos the position in the list of buttons to select
*/
private void clickUnitButton(final int buttonPos) {
//pop open selection dialog for historical units
if (mUnitType.isUnitHistorical(buttonPos)){
UnitHistCurrency uhc = (UnitHistCurrency) mUnitType.getUnit(buttonPos);
AlertDialog.Builder builder = new AlertDialog.
Builder(getActivity());
builder.setTitle(getText(R.string.historical_dialog_title));
builder.setSingleChoiceItems(uhc.getPossibleYearsReversed(), uhc.getReversedYearIndex(),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int item) {
dialog.dismiss();
UnitHistCurrency uhc = (UnitHistCurrency) mUnitType.getUnit(buttonPos);
uhc.setYearIndexReversed(item);
refreshButtonText(buttonPos);
tryConvert(buttonPos);
}
});
//null seems to do the same as canceling the dialog
builder.setNegativeButton(android.R.string.cancel, null);
AlertDialog alert = builder.create();
alert.show();
}
//for historical units, only perform after dialog is gone
else
tryConvert(buttonPos);
}
private void tryConvert(int buttonPos) {
//Clear color and arrows from previously selected convert buttons
clearButtonSelection();
//Set select unit, also this will potentially call convert if we already have a selected unit
boolean requestConvert = mUnitType.selectUnit(buttonPos);
Calculator calc = Calculator.getCalculator(getActivity());
//unit previously selected, we pressed another, do a convert
if (requestConvert){
calc.convertFromTo(mUnitType.getPrevUnit(), mUnitType.getCurrUnit());
clearButtonSelection();
}
//unit not previously selected, now select one
else if (mUnitType.isUnitSelected()){
// clear out solved flag
calc.setSolved(false);
//if expression was blank, add a highlighted "1"
if (calc.isExpressionEmpty()){
//add in a 1 for user's convenience
calc.parseKeyPressed("1");
//highlight it
calc.setSelection(0, calc.toString().length());
}
colorSelectedButton();
}
//always update screen to add/remove unit from expression
mCallback.updateScreen(true);
}
private void colorSelectedButton() {
//is null when app's onResume calls it (convertkey's onCreate called after activity's onResume)
if (mUnitType == null)
return;
if (mUnitType.isUnitSelected()){
for (int i = 0; i < mConvButton.size(); i++) {
if (i != mUnitType.getCurrUnitButtonPos()){
refreshButtonText(getResources().getString(R.string.convert_arrow), i);
}
}
setSelectedButtonHighlight(true);
}
}
private void updateFavorites(int clickedButtonPos) {
//only populate a favorite units if we have a min numb items in the dialog
if (NUM_UNITS_REQUIRED_FOR_FAVORITES > (mUnitType.size()))
return;
int indexLastMoreFav = mNumConvButtons + NUM_MORE_FAVORITES - 1;
mUnitType.swapUnits(clickedButtonPos, indexLastMoreFav);
mUnitType.rotateUnitSublist(mNumConvButtons, indexLastMoreFav + 1);
mUnitType.sortUnitSublist(indexLastMoreFav + 1, mUnitType.size());
}
/**
* Clears the button unit selection
*/
public void clearButtonSelection() {
//function may be called before convert key array built, in which case, leave
if (mConvButton == null) return;
//remove arrows
for (int i = 0; i < mConvButton.size(); i++) {
refreshButtonText("", i);
}
//Clear color from previously selected convert button
setSelectedButtonHighlight(false);
//clear the button in the calc
// mUnitType.clearUnitSelection();
}
private void setSelectedButtonHighlight(boolean highlighted) {
mCallback.setEqualButtonColor(highlighted);
//Don't color if "More" button was selected
if (mUnitType.getCurrUnitButtonPos() < mNumConvButtons){
int currButtonPos = mUnitType.getCurrUnitButtonPos();
//if no button is selected, return
if (currButtonPos == -1)
return;
// this fixes a bug when currency is selected and app leaves, and we
// reload, currency is still selected and this is a null pointer
if (currButtonPos >= mConvButton.size())
return;
//set the current button to highlighted or not
mConvButton.get(currButtonPos).setSelected(highlighted);
}
}
}