package org.adaptlab.chpir.android.survey;
import java.util.Date;
import org.adaptlab.chpir.android.survey.Models.Instrument;
import org.adaptlab.chpir.android.survey.Models.Question;
import org.adaptlab.chpir.android.survey.Models.Response;
import org.adaptlab.chpir.android.survey.Models.ResponsePhoto;
import org.adaptlab.chpir.android.survey.Models.Survey;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.activeandroid.Model;
public abstract class QuestionFragment extends Fragment {
protected final static String LIST_DELIMITER = ",";
protected abstract void createQuestionComponent(ViewGroup questionComponent);
protected abstract String serialize();
protected abstract void deserialize(String responseText);
public TextView mValidationTextView;
private Question mQuestion;
private Survey mSurvey;
public Response mResponse;
private Instrument mInstrument;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
init();
}
public void init() {
long questionId = getArguments().getLong(QuestionFragmentFactory.EXTRA_QUESTION_ID, -1);
long surveyId = getArguments().getLong(QuestionFragmentFactory.EXTRA_SURVEY_ID, -1);
if (questionId != -1 && surveyId != -1) {
mQuestion = Question.findByRemoteId(questionId);
mSurvey = Model.load(Survey.class, surveyId);
mResponse = loadOrCreateResponse();
mResponse.setQuestion(mQuestion);
mResponse.setSurvey(mSurvey);
mInstrument = mSurvey.getInstrument();
}
saveTimeStarted();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_question_factory, parent,
false);
ViewGroup questionComponent = (LinearLayout) v.findViewById(R.id.question_component);
mValidationTextView = (TextView) v.findViewById(R.id.validation_text);
// Overridden by subclasses to place their graphical elements on the fragment.
createQuestionComponent(questionComponent);
deserialize(mResponse.getText());
return v;
}
public Question getQuestion() {
return mQuestion;
}
protected Survey getSurvey() {
return mSurvey;
}
public Response getResponse() {
return mResponse;
}
public Instrument getInstrument() {
return mInstrument;
}
public String getSpecialResponse() {
if (getResponse() != null) {
return getResponse().getSpecialResponse();
} else {
return "";
}
}
protected ResponsePhoto getResponsePhoto() {
return getResponse().getResponsePhoto();
}
/*
* An otherText is injected from a subclass. This gives
* the majority of the control to the otherText to the subclass,
* but the things that all other text fields have in common
* can go here.
*/
public void addOtherResponseView(EditText otherText) {
otherText.setHint(R.string.other_specify_edittext);
otherText.setEnabled(false);
otherText.setInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
otherText.addTextChangedListener(new TextWatcher() {
public void onTextChanged(CharSequence s, int start, int before,
int count) {
saveOtherResponse(s.toString());
}
// Required by interface
public void beforeTextChanged(CharSequence s, int start,
int count, int after) { }
public void afterTextChanged(Editable s) { }
});
if (getResponse().getOtherResponse() != null) {
otherText.setText(getResponse().getOtherResponse());
}
}
public void saveOtherResponse(String response) {
getResponse().setOtherResponse(response);
getResponse().setDeviceUser(AuthUtils.getCurrentUser());
getResponse().save();
}
/*
* Display warning to user if response does not match regular
* expression in question. Disable next button if not valid.
* Only save if valid.
*/
public void saveResponseWithValidation() {
getResponse().setDeviceUser(AuthUtils.getCurrentUser());
if (getResponse().saveWithValidation()) {
animateValidationTextView(true);
} else {
animateValidationTextView(false);
}
// Refresh options menu to reflect response validation status.
if (isAdded()) {
ActivityCompat.invalidateOptionsMenu(getActivity());
}
}
protected void saveResponse() {
getResponse().setResponse(serialize());
saveTimeEnded();
saveResponseWithValidation();
if (isAdded() && !mResponse.getText().equals("")) {
mResponse.setSpecialResponse("");
ActivityCompat.invalidateOptionsMenu(getActivity());
}
}
public void saveSpecialResponse(String specialResponse) {
Response response = getResponse();
if (response != null) {
response.setSpecialResponse(specialResponse);
response.setResponse("");
response.setDeviceUser(AuthUtils.getCurrentUser());
saveTimeEnded();
response.save();
deserialize(response.getText());
}
}
private void saveTimeStarted() {
if (getResponse().getTimeStarted() == null) {
getResponse().setTimeStarted(new Date());
getResponse().save();
}
}
private void saveTimeEnded() {
getResponse().setTimeEnded(new Date());
}
private Response loadOrCreateResponse() {
if (mSurvey.getResponseByQuestion(getQuestion()) != null) {
return mSurvey.getResponseByQuestion(getQuestion());
} else {
return new Response();
}
}
private void animateValidationTextView(boolean valid) {
Animation animation = new AlphaAnimation(0, 0);
if (valid) {
if (mValidationTextView.getVisibility() == TextView.VISIBLE)
animation = new AlphaAnimation(1, 0);
mValidationTextView.setVisibility(TextView.INVISIBLE);
} else {
animation = new AlphaAnimation(0, 1);
mValidationTextView.setVisibility(TextView.VISIBLE);
if (mQuestion.getRegExValidationMessage() != null)
mValidationTextView.setText(mQuestion.getRegExValidationMessage());
else
mValidationTextView.setText(R.string.not_valid_response);
}
animation.setDuration(1000);
if (mValidationTextView.getAnimation() == null ||
mValidationTextView.getAnimation().hasEnded() ||
!mValidationTextView.getAnimation().hasStarted()) {
// Only animate if not currently animating
mValidationTextView.setAnimation(animation);
}
}
}