/*******************************************************************************
* Copyright 2011 The Regents of the University of California
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package org.ohmage.triggers.types.time;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import org.ohmage.R;
import org.ohmage.logprobe.Analytics;
import org.ohmage.logprobe.Log;
import org.ohmage.logprobe.LogProbe.Status;
import org.ohmage.triggers.base.TriggerActionDesc;
import org.ohmage.triggers.config.TrigUserConfig;
import org.ohmage.triggers.ui.ActionSelectorView;
import org.ohmage.triggers.ui.TriggerListActivity;
import org.ohmage.triggers.utils.TimePickerPreference;
import java.util.LinkedHashMap;
public class TimeTrigEditActivity extends PreferenceActivity
implements View.OnClickListener,
OnPreferenceClickListener,
OnPreferenceChangeListener,
DialogInterface.OnMultiChoiceClickListener,
DialogInterface.OnClickListener {
private static final String TAG = "TimeTrigEditActivity";
public static final String KEY_TRIG_DESC = "trig_desc";
public static final String KEY_ACT_DESC = "act_desc";
public static final String KEY_TRIG_ID = "trig_id";
public static final String KEY_ADMIN_MODE = "admin_mode";
private static final String KEY_SAVE_DAYS = "days";
private static final String KEY_SAVE_REPEAT_STATUS = "repeat_status";
private static final String PREF_KEY_TRIGGER_TIME = "trigger_time";
// private static final String PREF_KEY_RANDOMIZE = "randomize_trigger_time";
private static final String PREF_KEY_ENABLE_RANGE = "enable_time_range";
private static final String PREF_KEY_START_TIME = "interval_start_time";
private static final String PREF_KEY_END_TIME = "interval_end_time";
private static final String PREF_KEY_REPEAT_DAYS = "repeat_days";
private static final String PREF_KEY_ACTIONS = "actions";
private static final int DIALOG_ID_REPEAT_SEL = 0;
private static final int DIALOG_ID_INVALID_TIME_ALERT = 1;
private static final int DIALOG_ID_ACTION_SEL = 2;
private static final int DIALOG_ID_NO_SURVEYS_SELECTED = 3;
private TimeTrigDesc mTrigDesc;
private TriggerActionDesc mActDesc;
private String[] mDays;
private boolean[] mRepeatStatus;
private boolean mAdminMode = false;
private AlertDialog mRepeatDialog = null;
private String[] mActions;
private boolean[] mActSelected = null;
public interface ExitListener {
public void onDone(Context context, int trigId, String trigDesc, String actDesc);
}
private static ExitListener mExitListener = null;
private int mTrigId = 0;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.trig_time_edit_preferences);
setContentView(R.layout.trigger_editor);
mTrigDesc = new TimeTrigDesc();
mActDesc = new TriggerActionDesc();
if(getIntent().hasExtra(TriggerListActivity.KEY_ACTIONS)) {
mActions = getIntent().getStringArrayExtra(TriggerListActivity.KEY_ACTIONS);
} else {
Log.e(TAG, "TimeTrigEditActivity: Invoked with out passing surveys");
finish();
return;
}
PreferenceScreen screen = getPreferenceScreen();
int prefCount = screen.getPreferenceCount();
for(int i = 0; i < prefCount; i++) {
screen.getPreference(i).setOnPreferenceClickListener(this);
screen.getPreference(i).setOnPreferenceChangeListener(this);
}
((Button) findViewById(R.id.trig_edit_done)).setOnClickListener(this);
((Button) findViewById(R.id.trig_edit_cancel)).setOnClickListener(this);
String config = null;
String action = null;
if(savedInstanceState != null) {
config = savedInstanceState.getString(KEY_TRIG_DESC);
action = savedInstanceState.getString(KEY_ACT_DESC);
}
else {
config = getIntent().getStringExtra(KEY_TRIG_DESC);
action = getIntent().getStringExtra(KEY_ACT_DESC);
}
mAdminMode = getIntent().getBooleanExtra(KEY_ADMIN_MODE, false);
if(config != null) {
mTrigId = getIntent().getIntExtra(KEY_TRIG_ID, 0);
if(mTrigDesc.loadString(config) && mActDesc.loadString(action)) {
initializeGUI();
}
else {
getPreferenceScreen().setEnabled(false);
Toast.makeText(this, R.string.trigger_invalid_settings,
Toast.LENGTH_SHORT).show();
}
}
if(savedInstanceState == null) {
LinkedHashMap<String, Boolean> repeatList = mTrigDesc.getRepeat();
mDays = repeatList.keySet()
.toArray(new String[repeatList.size()]);
mRepeatStatus = new boolean[mDays.length];
updateRepeatStatusArray();
// if there are any preselected actions specified when the activity is first created
// and there's currently nothing in the action description, load the selected options
// into the action description as if they were previously selected
if (mActDesc.getCount() <= 0 && getIntent().hasExtra(TriggerListActivity.KEY_PRESELECTED_ACTIONS)) {
String[] preselectedActions = getIntent().getStringArrayExtra(TriggerListActivity.KEY_PRESELECTED_ACTIONS);
for (int i = 0; i < preselectedActions.length; ++i) {
mActDesc.addSurvey(preselectedActions[i]);
}
updateActionsPrefStatus();
}
}
else {
mDays = savedInstanceState.getStringArray(KEY_SAVE_DAYS);
mRepeatStatus = savedInstanceState.getBooleanArray(KEY_SAVE_REPEAT_STATUS);
}
}
@Override
protected void onResume() {
super.onResume();
Analytics.activity(this, Status.ON);
}
@Override
protected void onPause() {
super.onPause();
Analytics.activity(this, Status.OFF);
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
udateTriggerDesc();
outState.putString(KEY_TRIG_DESC, mTrigDesc.toString());
outState.putString(KEY_ACT_DESC, mActDesc.toString());
outState.putStringArray(KEY_SAVE_DAYS, mDays);
outState.putBooleanArray(KEY_SAVE_REPEAT_STATUS, mRepeatStatus);
}
public static void setOnExitListener(ExitListener listener) {
mExitListener = listener;
}
@SuppressWarnings("unused")
private void initializeGUI() {
TimePickerPreference trigTimePref = (TimePickerPreference) getPreferenceScreen()
.findPreference(PREF_KEY_TRIGGER_TIME);
CheckBoxPreference rangePref = (CheckBoxPreference) findPreference(PREF_KEY_ENABLE_RANGE);
// CheckBoxPreference randPref = (CheckBoxPreference) findPreference(PREF_KEY_RANDOMIZE);
TimePickerPreference startPref = (TimePickerPreference) getPreferenceScreen()
.findPreference(PREF_KEY_START_TIME);
TimePickerPreference endPref = (TimePickerPreference) getPreferenceScreen()
.findPreference(PREF_KEY_END_TIME);
if(mTrigDesc.isRangeEnabled()) {
rangePref.setChecked(true);
/*
if(mTrigDesc.isRandomized() || SharedPreferencesHelper.TRIGGERS_TIMERANGE_ALWAYS_RANDOM) {
randPref.setChecked(true);
}
else {
trigTimePref.setTime(mTrigDesc.getTriggerTime());
}
*/
startPref.setTime(mTrigDesc.getRangeStart());
endPref.setTime(mTrigDesc.getRangeEnd());
}
else {
trigTimePref.setTime(mTrigDesc.getTriggerTime());
}
updateTriggerTimePrefStatus();
updateRepeatPrefStatus();
updateActionsPrefStatus();
if(!mAdminMode && !TrigUserConfig.editTimeTriggerTime) {
trigTimePref.setEnabled(false);
}
if(!mAdminMode && !TrigUserConfig.editTimeTriggerRange) {
rangePref.setEnabled(false);
}
if(!mAdminMode && !TrigUserConfig.editTimeTriggerRange) {
// randPref.setEnabled(false);
}
if(!mAdminMode && !TrigUserConfig.editTimeTriggerRange) {
startPref.setEnabled(false);
}
if(!mAdminMode && !TrigUserConfig.editTimeTriggerRange) {
endPref.setEnabled(false);
}
Preference repeatPref = getPreferenceScreen()
.findPreference(PREF_KEY_REPEAT_DAYS);
if(!mAdminMode && !TrigUserConfig.editTimeTriggerRepeat) {
repeatPref.setEnabled(false);
}
Preference actionsPref = getPreferenceScreen().findPreference(PREF_KEY_ACTIONS);
if(!mAdminMode && !TrigUserConfig.editTriggerActions) {
actionsPref.setEnabled(false);
}
((Button) findViewById(R.id.trig_edit_done))
.setEnabled(mAdminMode || TrigUserConfig.editTimeTrigger);
}
@SuppressWarnings("unused")
private void udateTriggerDesc() {
CheckBoxPreference rangePref = (CheckBoxPreference) findPreference(PREF_KEY_ENABLE_RANGE);
// CheckBoxPreference randPref = (CheckBoxPreference) findPreference(PREF_KEY_RANDOMIZE);
TimePickerPreference timePref = (TimePickerPreference) getPreferenceScreen()
.findPreference(PREF_KEY_TRIGGER_TIME);
TimePickerPreference startPref = (TimePickerPreference) getPreferenceScreen()
.findPreference(PREF_KEY_START_TIME);
TimePickerPreference endPref = (TimePickerPreference) getPreferenceScreen()
.findPreference(PREF_KEY_END_TIME);
if(rangePref.isChecked()) {
mTrigDesc.setRangeEnabled(true);
/*
if(randPref.isChecked() || SharedPreferencesHelper.TRIGGERS_TIMERANGE_ALWAYS_RANDOM) {
mTrigDesc.setRandomized(true);
}
else {
mTrigDesc.setRandomized(false);
mTrigDesc.setTriggerTime(timePref.getTime());
}
*/
// FAISAL: now we're always random when rangePref is true
mTrigDesc.setRandomized(true);
mTrigDesc.setRangeStart(startPref.getTime());
mTrigDesc.setRangeEnd(endPref.getTime());
}
else {
mTrigDesc.setRangeEnabled(false);
mTrigDesc.setRandomized(false);
mTrigDesc.setTriggerTime(timePref.getTime());
}
}
@Override
public void onClick(View v) {
switch(v.getId()) {
case R.id.trig_edit_done:
if(mExitListener != null) {
udateTriggerDesc();
if(!mTrigDesc.validate()) {
// if the time settings are invalid, tell the user and abort
showDialog(DIALOG_ID_INVALID_TIME_ALERT);
return;
}
else if (mActDesc.getSurveys().length <= 0) {
// if no surveys were selected, tell the user and abort
showDialog(DIALOG_ID_NO_SURVEYS_SELECTED);
return;
}
// since we didn't hit any issues, we must be good; invoke the exit handler which stores the trigger
mExitListener.onDone(this, mTrigId, mTrigDesc.toString(), mActDesc.toString());
}
break;
}
finish();
}
private void updateTriggerTimePrefStatus() {
TimePickerPreference trigTimePref = (TimePickerPreference) getPreferenceScreen()
.findPreference(PREF_KEY_TRIGGER_TIME);
CheckBoxPreference rangePref = (CheckBoxPreference) findPreference(PREF_KEY_ENABLE_RANGE);
// CheckBoxPreference randPref = (CheckBoxPreference) findPreference(PREF_KEY_RANDOMIZE);
// if triggers_timerange_always_random is set, then make randPref = rangePref
// randPref.setChecked(SharedPreferencesHelper.TRIGGERS_TIMERANGE_ALWAYS_RANDOM && rangePref.isChecked());
if(rangePref.isChecked()) {
trigTimePref.setSummary(R.string.trigger_time_randomized);
trigTimePref.setEnabled(false);
}
else {
trigTimePref.setSummary(trigTimePref.getTime().toString());
trigTimePref.setEnabled(true);
}
}
private void updateRepeatPrefStatus() {
Preference repeatPref = getPreferenceScreen()
.findPreference(PREF_KEY_REPEAT_DAYS);
repeatPref.setSummary(mTrigDesc.getRepeatDescription());
}
private void updateRepeatStatusArray() {
LinkedHashMap<String, Boolean> repeatList = mTrigDesc.getRepeat();
for(int i = 0; i < mDays.length; i++) {
mRepeatStatus[i] = repeatList.get(mDays[i]);
}
}
private void updateActionsPrefStatus() {
Preference actionsPref = getPreferenceScreen()
.findPreference(PREF_KEY_ACTIONS);
if (mActDesc.getSurveys().length > 0) {
actionsPref.setSummary(stringArrayToString(mActDesc.getSurveys()));
} else {
actionsPref.setSummary(R.string.trigger_no_actions);
}
}
private String stringArrayToString(String [] strings) {
if (strings.length == 0) {
return "";
}
String string = "";
for (String s : strings) {
string = string.concat(s).concat(", ");
}
return string.substring(0, string.length() - 2);
}
private Dialog createRepeatSelDialog() {
updateRepeatStatusArray();
mRepeatDialog = new AlertDialog.Builder(this)
.setTitle(R.string.trigger_time_select_days)
.setPositiveButton(R.string.done, this)
.setNegativeButton(R.string.cancel, this)
.setMultiChoiceItems(mDays, mRepeatStatus, this)
.create();
return mRepeatDialog;
}
private Dialog createInvalidTimeAlert() {
return new AlertDialog.Builder(this)
.setTitle(R.string.trigger_time_invalid_settings)
.setNegativeButton(R.string.cancel, null)
.setMessage(R.string.trigger_time_invalid_text)
.create();
}
private Dialog createNoSurveysSelectedAlert() {
return new AlertDialog.Builder(this)
.setTitle(R.string.trigger_time_no_survey_selected)
.setNegativeButton(R.string.cancel, null)
.setMessage(R.string.trigger_time_no_survey_selected_text)
.create();
}
@Override
protected Dialog onCreateDialog(int id) {
switch(id) {
case DIALOG_ID_REPEAT_SEL:
return createRepeatSelDialog();
case DIALOG_ID_INVALID_TIME_ALERT:
return createInvalidTimeAlert();
case DIALOG_ID_NO_SURVEYS_SELECTED:
return createNoSurveysSelectedAlert();
case DIALOG_ID_ACTION_SEL:
return createEditActionDialog();
}
return null;
}
@Override
public boolean onPreferenceClick(Preference pref) {
if(pref.getKey().equals(PREF_KEY_ENABLE_RANGE)) {
updateTriggerTimePrefStatus();
} else if(pref.getKey().equals(PREF_KEY_REPEAT_DAYS)) {
removeDialog(DIALOG_ID_REPEAT_SEL);
showDialog(DIALOG_ID_REPEAT_SEL);
} else if(pref.getKey().equals(PREF_KEY_ACTIONS)) {
removeDialog(DIALOG_ID_ACTION_SEL);
showDialog(DIALOG_ID_ACTION_SEL);
}
return false;
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
return true;
}
@Override
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
mRepeatStatus[which] = isChecked;
int repeatCount = 0;
for(int i = 0; i < mRepeatStatus.length; i++) {
if(mRepeatStatus[i]) {
repeatCount++;
}
}
if(mRepeatDialog != null) {
if(mRepeatDialog.isShowing()) {
mRepeatDialog.getButton(AlertDialog.BUTTON_POSITIVE)
.setEnabled(repeatCount != 0);
}
}
}
@Override
public void onClick(DialogInterface dialog, int which) {
if(which == DialogInterface.BUTTON_POSITIVE) {
for(int i = 0; i < mDays.length; i++) {
mTrigDesc.setRepeatStatus(mDays[i], mRepeatStatus[i]);
}
}
dialog.dismiss();
updateRepeatPrefStatus();
}
private Dialog createEditActionDialog() {
if(mActSelected == null) {
mActSelected = new boolean[mActions.length];
for(int i = 0; i < mActSelected.length; i++) {
mActSelected[i] = mActDesc.hasSurvey(mActions[i]);
}
}
AlertDialog.Builder builder =
new AlertDialog.Builder(this)
.setTitle(R.string.trigger_select_actions)
.setNegativeButton(R.string.cancel, null)
.setView(new ActionSelectorView(getBaseContext(), mActions, mActSelected));
/*
AlertDialog.Builder builder =
new AlertDialog.Builder(this)
.setTitle(R.string.trigger_select_actions)
.setNegativeButton(R.string.cancel, null)
.setMultiChoiceItems(mActions, mActSelected,
new DialogInterface.OnMultiChoiceClickListener() {
@Override
public void onClick(DialogInterface dialog, int which,
boolean isChecked) {
mActSelected[which] = isChecked;
}
});
*/
if(mAdminMode || TrigUserConfig.editTriggerActions) {
builder.setPositiveButton(R.string.done,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
mActDesc.clearAllSurveys();
for(int i = 0; i < mActSelected.length; i++) {
if(mActSelected[i]) {
mActDesc.addSurvey(mActions[i]);
}
}
dialog.dismiss();
updateActionsPrefStatus();
// handleActionSelection(mDialogTrigId, desc);
}
});
}
return builder.create();
}
/* public void handleActionSelection(int trigId, TriggerActionDesc desc) {
String prevActDesc = mDb.getActionDescription(trigId);
TriggerActionDesc prevDesc = new TriggerActionDesc();
prevDesc.loadString(prevActDesc);
mDb.updateActionDescription(trigId, desc.toString());
mCursor.requery();
Notifier.refreshNotification(this, mCampaignUrn, true);
if(desc.getCount() == 0 && prevDesc.getCount() !=0) {
toggleTrigger(trigId, false);
}
if(desc.getCount() != 0 && prevDesc.getCount() == 0) {
toggleTrigger(trigId, true);
}
}*/
}