/*
Copyright (C) 2013 Haowen Ning
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.liberty.android.fantastischmemo.ui;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.TextView;
import com.google.common.base.Strings;
import org.liberty.android.fantastischmemo.common.AMPrefKeys;
import org.liberty.android.fantastischmemo.common.AnyMemoDBOpenHelper;
import org.liberty.android.fantastischmemo.common.AnyMemoDBOpenHelperManager;
import org.liberty.android.fantastischmemo.R;
import org.liberty.android.fantastischmemo.common.BaseActivity;
import org.liberty.android.fantastischmemo.common.BaseDialogFragment;
import org.liberty.android.fantastischmemo.dao.CardDao;
import org.liberty.android.fantastischmemo.entity.Category;
import org.liberty.android.fantastischmemo.utils.AMPrefUtil;
import java.util.HashMap;
import java.util.Map;
import javax.inject.Inject;
public class QuizLauncherDialogFragment extends BaseDialogFragment {
public static final String EXTRA_DBPATH = "dbpath";
private static final int MAX_GROUP_SIZE = 100;
private static final int DEFAULT_GROUP_SIZE = 100;
private AnyMemoDBOpenHelper dbOpenHelper;
private CardDao cardDao;
private String dbPath = null;
private BaseActivity mActivity;
private Button startQuizButton;
private RadioButton quizByGroupRadio;
private RadioButton quizByCategoryRadio;
private RadioButton quizByRangeRadio;
private TextView quizGroupSizeTitle;
private EditText quizGroupSizeEdit;
private TextView quizGroupNumberTitle;
private EditText quizGroupNumberEdit;
private TextView quizRangeStartTitle;
private EditText quizRangeStartOrdinalEdit;
private TextView quizRangeEndTitle;
private EditText quizRangeEndOrdinalEdit;
private CheckBox shuffleCheckbox;
private Button categoryButton;
private int totalCardNumber;
private int groupSize;
private int groupNumber;
private int rangeStartOrdinal;
private int rangeEndOrdinal;
// Default category id is "uncategorized".
private int categoryId = 0;
private Category filterCategory;
private Map<CompoundButton, View> radioButtonSettingsMapping;
@Inject AMPrefUtil amPrefUtil;
public QuizLauncherDialogFragment() {}
@Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
fragmentComponents().inject(this);
Bundle extras = getArguments();
if (extras != null) {
dbPath = extras.getString(EXTRA_DBPATH);
}
}
@Override
public void onDestroy() {
super.onDestroy();
AnyMemoDBOpenHelperManager.releaseHelper(dbOpenHelper);
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
mActivity = (BaseActivity) context;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
View v = getActivity().getLayoutInflater().inflate(R.layout.quiz_launcher_dialog, null, false);
startQuizButton = (Button) v.findViewById(R.id.start_quiz_button);
startQuizButton.setOnClickListener(startQuizButtonOnClickListener);
quizByGroupRadio = (RadioButton) v.findViewById(R.id.quiz_by_group_radio);
quizByGroupRadio.setOnCheckedChangeListener(onCheckedChangeListener);
quizByCategoryRadio = (RadioButton) v.findViewById(R.id.quiz_by_category_radio);
quizByCategoryRadio.setOnCheckedChangeListener(onCheckedChangeListener);
quizGroupSizeTitle = (TextView) v.findViewById(R.id.quiz_group_size_title);
quizGroupSizeEdit = (EditText) v.findViewById(R.id.quiz_group_size);
// Make sure the text value is sanity and update other information
// about the group size and etc accordingly.
quizByRangeRadio = (RadioButton) v.findViewById(R.id.quiz_by_range_radio);
quizByRangeRadio.setOnCheckedChangeListener(onCheckedChangeListener);
quizGroupSizeEdit.addTextChangedListener(quizByGroupSizeTextWatcher);
quizGroupSizeEdit.setOnFocusChangeListener(sanitizeInputListener);
quizGroupNumberTitle = (TextView) v.findViewById(R.id.quiz_group_number_title);
quizGroupNumberEdit = (EditText) v.findViewById(R.id.quiz_group_number);
quizGroupNumberEdit.addTextChangedListener(quizByGroupNumberTextWatcher);
quizGroupNumberEdit.setOnFocusChangeListener(sanitizeInputListener);
//For quiz range
quizRangeStartTitle = (TextView) v.findViewById(R.id.quiz_range_start_size_title);
quizRangeEndTitle = (TextView) v.findViewById(R.id.quiz_range_end_size_title);
quizRangeStartOrdinalEdit = (EditText) v.findViewById(R.id.quiz_range_strat_ordinal);
quizRangeStartOrdinalEdit.addTextChangedListener(quizByRangeStartTextWatcher);
quizRangeStartOrdinalEdit.setOnFocusChangeListener(rangeInputListener);
quizRangeEndOrdinalEdit = (EditText) v.findViewById(R.id.quiz_range_end_ordinal);
quizRangeEndOrdinalEdit.addTextChangedListener(quizByRangeEndTextWatcher);
quizRangeEndOrdinalEdit.setOnFocusChangeListener(rangeInputListener);
categoryButton = (Button) v.findViewById(R.id.category_button);
categoryButton.setOnClickListener(categoryButtonListener);
radioButtonSettingsMapping = new HashMap<CompoundButton, View>(2);
radioButtonSettingsMapping.put(quizByGroupRadio, v.findViewById(R.id.quiz_by_group_settings));
radioButtonSettingsMapping.put(quizByCategoryRadio, v.findViewById(R.id.quiz_by_category_settings));
radioButtonSettingsMapping.put(quizByRangeRadio, v.findViewById(R.id.quiz_by_range_settings));
shuffleCheckbox = (CheckBox) v.findViewById(R.id.shuffle_checkbox);
return new AlertDialog.Builder(getActivity())
.setTitle(R.string.quiz_text)
.setView(v)
.create();
}
@Override
public void onStart() {
super.onStart();
dbOpenHelper = AnyMemoDBOpenHelperManager.getHelper(mActivity, dbPath);
InitTask task = new InitTask();
task.execute((Void)null);
}
private CompoundButton.OnCheckedChangeListener onCheckedChangeListener
= new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
View settingsView = radioButtonSettingsMapping.get(buttonView);
if (isChecked) {
settingsView.setVisibility(View.VISIBLE);
} else {
settingsView.setVisibility(View.GONE);
}
}
};
private View.OnClickListener startQuizButtonOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
if (quizByCategoryRadio.isChecked()) {
Intent intent = new Intent(mActivity, QuizActivity.class);
intent.putExtra(QuizActivity.EXTRA_DBPATH, dbPath);
intent.putExtra(QuizActivity.EXTRA_CATEGORY_ID, categoryId);
intent.putExtra(QuizActivity.EXTRA_SHUFFLE_CARDS, shuffleCheckbox.isChecked());
startActivity(intent);
} else if(quizByRangeRadio.isChecked()) {
Intent intent = new Intent(mActivity, QuizActivity.class);
int startOrd = Integer.parseInt(quizRangeStartOrdinalEdit.getText().toString());
int endOrd = Integer.parseInt(quizRangeEndOrdinalEdit.getText().toString());
int size = endOrd - startOrd + 1;
amPrefUtil.putSavedInt(AMPrefKeys.QUIZ_START_ORDINAL_KEY, dbPath, rangeStartOrdinal);
amPrefUtil.putSavedInt(AMPrefKeys.QUIZ_END_ORDINAL_KEY, dbPath, rangeEndOrdinal);
intent.putExtra(QuizActivity.EXTRA_DBPATH, dbPath);
intent.putExtra(QuizActivity.EXTRA_START_CARD_ORD, startOrd);
intent.putExtra(QuizActivity.EXTRA_QUIZ_SIZE, size);
intent.putExtra(QuizActivity.EXTRA_SHUFFLE_CARDS, shuffleCheckbox.isChecked());
startActivity(intent);
} else{
Intent intent = new Intent(mActivity, QuizActivity.class);
amPrefUtil.putSavedInt(AMPrefKeys.QUIZ_GROUP_SIZE_KEY, dbPath, groupSize);
amPrefUtil.putSavedInt(AMPrefKeys.QUIZ_GROUP_NUMBER_KEY, dbPath, groupNumber);
int startOrd = (groupNumber - 1) * groupSize + 1;
intent.putExtra(QuizActivity.EXTRA_DBPATH, dbPath);
intent.putExtra(QuizActivity.EXTRA_START_CARD_ORD, startOrd);
intent.putExtra(QuizActivity.EXTRA_QUIZ_SIZE, groupSize);
intent.putExtra(QuizActivity.EXTRA_SHUFFLE_CARDS, shuffleCheckbox.isChecked());
startActivity(intent);
}
}
};
private View.OnClickListener categoryButtonListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
showCategoriesDialog();
}
};
/*
* This task will mainly populate the categoryList
*/
private class InitTask extends AsyncTask<Void, Void, Void> {
@Override
public void onPreExecute() {
}
@Override
public Void doInBackground(Void... params) {
cardDao = dbOpenHelper.getCardDao();
totalCardNumber = (int)cardDao.getTotalCount(filterCategory);
return null;
}
@Override
public void onPostExecute(Void nothing) {
groupSize = amPrefUtil.getSavedInt(AMPrefKeys.QUIZ_GROUP_SIZE_KEY, dbPath, DEFAULT_GROUP_SIZE);
groupNumber = amPrefUtil.getSavedInt(AMPrefKeys.QUIZ_GROUP_NUMBER_KEY, dbPath, 1);
setGroupSizeText();
setGroupNumberText();
rangeStartOrdinal = amPrefUtil.getSavedInt(AMPrefKeys.QUIZ_START_ORDINAL_KEY, dbPath, 1);
rangeEndOrdinal = amPrefUtil.getSavedInt(AMPrefKeys.QUIZ_END_ORDINAL_KEY, dbPath, 1);
quizRangeStartOrdinalEdit.setText("" + rangeStartOrdinal);
quizRangeEndOrdinalEdit.setText("" + rangeEndOrdinal);
quizRangeStartTitle.setText(getString(R.string.start_ordinal_text)
+ " (" + 1 + "-" + totalCardNumber + ")");
quizRangeEndTitle.setText(getString(R.string.end_ordinal_text)
+ " (" + rangeStartOrdinal + "-" + totalCardNumber + ")");
}
}
private void setGroupSizeText() {
if (totalCardNumber < groupSize) {
groupSize = totalCardNumber;
}
int maxGroupSize = Math.min(totalCardNumber, MAX_GROUP_SIZE);
// If maxGroupNumberis 0, Math.min(maxGroupSize, 1) will display 0
quizGroupSizeTitle.setText(getString(R.string.quiz_group_size_text)
+ " (" + Math.min(maxGroupSize, 1) + "-" + maxGroupSize + ")");
if (Strings.isNullOrEmpty(quizGroupSizeEdit.getText().toString())) {
quizGroupSizeEdit.setText("" + groupSize);
}
}
private void setGroupNumberText() {
// The groupSize can be 0, so use max (1, groupSize) to
// fix divided by zero problem
int maxGroupNumber = (totalCardNumber - 1) / Math.max(1, groupSize) + 1;
if (groupNumber > maxGroupNumber) {
groupNumber = maxGroupNumber;
}
// If maxGroupNumberis 0, Math.min(maxGroupNumber, 1) will display 0
quizGroupNumberTitle.setText(getString(R.string.quiz_group_number_text)
+ " (" + Math.min(maxGroupNumber, 1) + "-" + maxGroupNumber + ")");
if (Strings.isNullOrEmpty(quizGroupNumberEdit.getText().toString())) {
quizGroupNumberEdit.setText("" + groupNumber);
}
}
private TextWatcher quizByGroupSizeTextWatcher = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// Nothing happened
}
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
// Nothing happened
}
@Override
public void afterTextChanged(Editable s) {
if (s == null || Strings.isNullOrEmpty(s.toString())) {
return;
}
try {
groupSize = Integer.valueOf(quizGroupSizeEdit.getText().toString());
if (groupSize <= 0) {
groupSize = 1;
}
if (groupSize > MAX_GROUP_SIZE) {
groupSize = MAX_GROUP_SIZE;
}
} catch (NumberFormatException e) {
groupSize = MAX_GROUP_SIZE;
}
setGroupSizeText();
}
};
private TextWatcher quizByGroupNumberTextWatcher = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// Nothing happened
}
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
// Nothing happened
}
@Override
public void afterTextChanged(Editable s) {
if (s == null || Strings.isNullOrEmpty(s.toString())) {
return;
}
try {
groupNumber = Integer.valueOf(quizGroupNumberEdit.getText().toString());
if (groupNumber < 1) {
groupNumber = 1;
}
} catch (NumberFormatException e) {
groupNumber = 1;
}
setGroupNumberText();
}
};
private TextWatcher quizByRangeStartTextWatcher = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// Nothing happened
}
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
// Nothing happened
}
@Override
public void afterTextChanged(Editable s) {
if (s == null || Strings.isNullOrEmpty(s.toString())) {
return;
}
try {
rangeStartOrdinal = Integer.valueOf(quizRangeStartOrdinalEdit.getText().toString());
if (rangeStartOrdinal <= 0) {
rangeStartOrdinal = 1;
}
if (rangeStartOrdinal > totalCardNumber) {
rangeStartOrdinal = totalCardNumber;
}
} catch (NumberFormatException e) {
rangeStartOrdinal = 1;
}
//Set relative TextView
quizRangeEndTitle.setText(getString(R.string.end_ordinal_text)
+ " (" + rangeStartOrdinal + "-" + totalCardNumber + ")");
}
};
private TextWatcher quizByRangeEndTextWatcher = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// Nothing happened
}
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
// Nothing happened
}
@Override
public void afterTextChanged(Editable s) {
if (s == null || Strings.isNullOrEmpty(s.toString())) {
return;
}
try {
rangeEndOrdinal = Integer.valueOf(quizRangeEndOrdinalEdit.getText().toString());
if (rangeEndOrdinal <= 0) {
rangeEndOrdinal = 1;
}
//Make EndOrdinal >= StartOrdinal
if (rangeEndOrdinal < rangeStartOrdinal) {
rangeEndOrdinal = rangeStartOrdinal;
}
if (rangeEndOrdinal > totalCardNumber) {
rangeEndOrdinal = totalCardNumber;
}
} catch (NumberFormatException e) {
rangeEndOrdinal = totalCardNumber;
}
//Set relative TextView
quizRangeStartTitle.setText(getString(R.string.start_ordinal_text)
+ " (" + 1 + "-" + rangeEndOrdinal + ")");
}
};
View.OnFocusChangeListener rangeInputListener =
new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus == false) {
quizRangeStartOrdinalEdit.setText("" + rangeStartOrdinal);
quizRangeEndOrdinalEdit.setText("" + rangeEndOrdinal);
}
}
};
View.OnFocusChangeListener sanitizeInputListener =
new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus == false) {
quizGroupSizeEdit.setText("" + groupSize);
quizGroupNumberEdit.setText("" + groupNumber);
}
}
};
private void showCategoriesDialog() {
CategoryEditorFragment df = new CategoryEditorFragment();
df.setResultListener(categoryResultListener);
Bundle b = new Bundle();
b.putString(CategoryEditorFragment.EXTRA_DBPATH, dbPath);
b.putInt(CategoryEditorFragment.EXTRA_CATEGORY_ID, categoryId);
df.setArguments(b);
df.show(mActivity.getSupportFragmentManager(), "CategoryEditDialog");
mActivity.getSupportFragmentManager().findFragmentByTag("CategoryEditDialog");
}
// When a category is selected in category fragment.
private CategoryEditorFragment.CategoryEditorResultListener categoryResultListener =
new CategoryEditorFragment.CategoryEditorResultListener() {
public void onReceiveCategory(Category c) {
assert c != null : "The category got shouldn't be null.";
categoryId = c.getId();
if (Strings.isNullOrEmpty(c.getName())) {
categoryButton.setText(R.string.uncategorized_text);
} else {
categoryButton.setText(c.getName());
}
}
};
}