/*
* Copyright 2014 Bevbot LLC <info@bevbot.com>
*
* This file is part of the Kegtab package from the Kegbot project. For
* more information on Kegtab or Kegbot, see <http://kegbot.org/>.
*
* Kegtab 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, version 2.
*
* Kegtab 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 Kegtab. If not, see <http://www.gnu.org/licenses/>.
*/
package org.kegbot.app.setup;
import android.app.ActionBar;
import android.app.Activity;
import android.app.DialogFragment;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.DialogInterface;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import com.google.common.collect.Lists;
import org.kegbot.app.KegbotApplication;
import org.kegbot.app.R;
import org.kegbot.app.service.KegbotCoreService;
import java.util.List;
/**
* @author mike wakerly (mike@wakerly.com)
*/
public class SetupActivity extends Activity {
private static final String TAG = SetupActivity.class.getSimpleName();
public static final int SETUP_VERSION = 6;
private SetupStep mCurrentStep = null;
private final List<SetupStep> mTaskHistory = Lists.newArrayList();
private Button mBackButton;
private Button mNextButton;
private DialogFragment mDialog;
private AsyncTask<Void, Void, Void> mValidatorTask;
public static final String EXTRA_REASON = "reason";
public static final String EXTRA_REASON_UPGRADE = "upgrade";
public static final String EXTRA_REASON_USER = "user";
private static final int MESSAGE_GO_BACK = 100;
private static final int MESSAGE_START_VALIDATION = 101;
private static final int MESSAGE_VALIDATION_ABORTED = 102;
public interface SetupState {
public void setNextButtonEnabled(boolean enabled);
public void setNextButtonText(int resource);
}
private final SetupState mSetupState = new SetupState() {
@Override
public void setNextButtonEnabled(boolean enabled) {
mNextButton.setEnabled(enabled);
}
@Override
public void setNextButtonText(int resource) {
mNextButton.setText(resource);
}
};
private final Handler mHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_GO_BACK:
dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK));
dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK));
break;
case MESSAGE_START_VALIDATION:
startValidation();
break;
case MESSAGE_VALIDATION_ABORTED:
cancelValidation();
showAlertDialog("Verification aborted; please try again.");
break;
default:
super.handleMessage(msg);
}
}
};
/**
* Listener for the on-screen "back" button. Currently just simulates a "back" press.
*/
private final OnClickListener mBackListener = new OnClickListener() {
@Override
public void onClick(View v) {
Log.d(TAG, "Back pressed.");
mHandler.sendEmptyMessage(MESSAGE_GO_BACK);
}
};
private final OnClickListener mNextListener = new OnClickListener() {
@Override
public void onClick(View v) {
Log.d(TAG, "Next pressed.");
mHandler.sendEmptyMessage(MESSAGE_START_VALIDATION);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.setup_activity);
KegbotCoreService.stopService(this);
}
@Override
protected void onResume() {
super.onResume();
final ActionBar actionBar = getActionBar();
if (actionBar != null) {
actionBar.hide();
}
mBackButton = (Button) findViewById(R.id.setupBackButton);
mBackButton.setOnClickListener(mBackListener);
mNextButton = (Button) findViewById(R.id.setupNextButton);
mNextButton.setOnClickListener(mNextListener);
if (mCurrentStep == null) {
final String reason = getIntent().getStringExtra(EXTRA_REASON);
final SetupStep initialStep;
if (EXTRA_REASON_USER.equals(reason)) {
initialStep = new SetupSelectBackendStep(mSetupState);
} else if (EXTRA_REASON_UPGRADE.equals(reason)) {
initialStep = new SetupWelcomeStep(mSetupState);
} else {
initialStep = new SetupWelcomeStep(mSetupState);
}
setTask(initialStep);
}
}
private void showAlertDialog(String message) {
hideDialog();
final DialogFragment dialog = SetupAlertDialogFragment.newInstance(message);
dialog.show(getFragmentManager(), "dialog");
}
private void showProgressDialog() {
hideDialog();
mDialog = new SetupProgressDialogFragment(new SetupProgressDialogFragment.Listener() {
@Override
public void onCancel(DialogInterface dialog) {
mHandler.sendEmptyMessage(MESSAGE_VALIDATION_ABORTED);
}
});
mDialog.show(getFragmentManager(), "dialog");
}
private void hideDialog() {
if (mDialog != null) {
mDialog.dismiss();
mDialog = null;
}
}
private void startValidation() {
Log.d(TAG, "Starting validation: " + mCurrentStep);
mValidatorTask = new AsyncTask<Void, Void, Void>() {
private SetupValidationException mValidationError;
private SetupStep mNextStep;
@Override
protected void onPreExecute() {
showProgressDialog();
}
@Override
protected Void doInBackground(Void... params) {
mValidationError = null;
mNextStep = null;
try {
mNextStep = mCurrentStep.advance();
} catch (SetupValidationException e) {
mValidationError = e;
}
return null;
}
@Override
protected void onPostExecute(Void avoid) {
if (!isCancelled()) {
hideDialog();
if (mValidationError == null) {
onValidationSuccess(mNextStep);
} else {
onValidationFailure(mValidationError);
}
}
}
};
mValidatorTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
}
private void cancelValidation() {
if (mValidatorTask != null) {
mValidatorTask.cancel(true);
}
}
private void onValidationFailure(final SetupValidationException error) {
Log.d(TAG, "Validation unsuccessful: " + error, error);
showAlertDialog(error.getMessage());
}
private void onValidationSuccess(final SetupStep nextStep) {
Log.d(TAG, "Validation successful, next step=" + nextStep);
setTask(nextStep);
}
private void setTask(SetupStep step) {
if (step == null) {
Log.d(TAG, "Null task, finishing.");
KegbotApplication.get(this).getConfig().setSetupVersion(SETUP_VERSION);
setResult(RESULT_OK);
mTaskHistory.clear();
finish();
return;
}
Log.d(TAG, "Loading SetupStep: " + step);
step.onDisplay();
mCurrentStep = step;
mTaskHistory.add(step);
Fragment contentFragment = step.getContentFragment();
Fragment controlsFragment = step.getControlsFragment();
if (controlsFragment == null) {
controlsFragment = new SetupEmptyFragment();
}
FragmentManager fragmentManager = getFragmentManager();
final FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.setupContentFragment, contentFragment);
transaction.replace(R.id.setupControlsFragment, controlsFragment);
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
transaction.addToBackStack(null);
transaction.commit();
}
private void popTask() {
mTaskHistory.remove(mTaskHistory.size() - 1);
if (!mTaskHistory.isEmpty()) {
mCurrentStep = mTaskHistory.get(mTaskHistory.size() - 1);
} else {
Log.d(TAG, "Popped last step.");
}
}
@Override
public void onBackPressed() {
popTask();
mCurrentStep.onDisplay();
if (mTaskHistory.isEmpty()) {
setResult(RESULT_CANCELED);
finish();
} else {
super.onBackPressed();
}
}
@Override
protected void onStart() {
super.onStart();
KegbotCoreService.stopService(this);
}
@Override
protected void onStop() {
hideDialog();
super.onStop();
}
}