/*
* Copyright (C) 2014-2017 Stichting Akvo (Akvo Foundation)
*
* This file is part of Akvo Flow.
*
* Akvo Flow 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 3 of the License, or
* (at your option) any later version.
*
* Akvo Flow 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 Akvo Flow. If not, see <http://www.gnu.org/licenses/>.
*/
package org.akvo.flow.ui.adapter;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.View;
import android.view.ViewGroup;
import org.akvo.flow.R;
import org.akvo.flow.domain.Question;
import org.akvo.flow.domain.QuestionGroup;
import org.akvo.flow.event.QuestionInteractionListener;
import org.akvo.flow.event.SurveyListener;
import org.akvo.flow.ui.view.QuestionGroupTab;
import org.akvo.flow.ui.view.QuestionView;
import org.akvo.flow.ui.view.SubmitTab;
import java.util.ArrayList;
import java.util.List;
import timber.log.Timber;
public class SurveyTabAdapter extends PagerAdapter implements ViewPager.OnPageChangeListener {
private final ViewPager mPager;
private List<QuestionGroup> mQuestionGroups;
private List<QuestionGroupTab> mQuestionGroupTabs;
private SubmitTab mSubmitTab;
public SurveyTabAdapter(Context context, ViewPager pager, SurveyListener surveyListener,
QuestionInteractionListener questionListener) {
mPager = pager;
init(context, surveyListener, questionListener);
}
private void init(Context context, SurveyListener surveyListener,
QuestionInteractionListener questionListener) {
mQuestionGroups = surveyListener.getQuestionGroups();
mQuestionGroupTabs = new ArrayList<>();
for (QuestionGroup group : mQuestionGroups) {
QuestionGroupTab questionGroupTab =
new QuestionGroupTab(context, group, surveyListener, questionListener);
mQuestionGroupTabs.add(questionGroupTab);
}
if (!surveyListener.isReadOnly()) {
mSubmitTab = new SubmitTab(context, surveyListener);
}
mPager.addOnPageChangeListener(this);
}
public void notifyOptionsChanged() {
for (QuestionGroupTab questionGroupTab : mQuestionGroupTabs) {
questionGroupTab.notifyOptionsChanged();// Spread the word
}
}
/**
* Check if the tab is loaded, and do so if it has not been loaded yet.
*/
private void loadTab(int position) {
QuestionGroupTab tab = mQuestionGroupTabs.get(position);
if (!tab.isLoaded()) {
Timber.d("Loading Tab #%d", position);
tab.load();
tab.loadState();
setupDependencies();// Dependencies might occur across tabs
}
}
public void reset() {
for (QuestionGroupTab questionGroupTab : mQuestionGroupTabs) {
if (questionGroupTab.isLoaded()) {
// Only care about the loaded tabs
questionGroupTab.loadState();
}
}
}
/**
* Attempt to display a particular question, based on the given ID.
* If the question is found, the containing tab will be scrolled to the question's position.
* Upon success the tab position will be returned, -1 otherwise
*/
public int displayQuestion(String questionId) {
for (int i = 0; i < mQuestionGroupTabs.size(); i++) {
QuestionGroupTab questionGroupTab = mQuestionGroupTabs.get(i);
if (questionGroupTab.displayQuestion(questionId)) {
return i;
}
}
return -1;
}
public void onPause() {
// Propagate onPause callback
for (QuestionGroupTab questionGroupTab : mQuestionGroupTabs) {
questionGroupTab.onPause();
}
}
public void onResume() {
// Propagate onResume callback
for (QuestionGroupTab questionGroupTab : mQuestionGroupTabs) {
questionGroupTab.onResume();
}
}
public void onDestroy() {
// Propagate onDestroy callback
for (QuestionGroupTab questionGroupTab : mQuestionGroupTabs) {
questionGroupTab.onDestroy();
}
}
public void onQuestionComplete(String questionId, Bundle data) {
for (QuestionGroupTab questionGroupTab : mQuestionGroupTabs) {
questionGroupTab.onQuestionComplete(questionId, data);
}
}
public QuestionView getQuestionView(String questionId) {
QuestionView questionView = null;
for (QuestionGroupTab questionGroupTab : mQuestionGroupTabs) {
questionView = questionGroupTab.getQuestionView(questionId);
if (questionView != null) {
break;
}
}
return questionView;
}
/**
* Sets up question dependencies across question groups and registers
* questionInteractionListeners on the dependent views. This should be
* called each time a new tab is hydrated. It will iterate over all
* questions in the survey and install dependencies and the
* questionInteractionListeners. After installation, it will check to see if
* the parent question contains a response. If so, it will fire a
* questionInteractionEvent to ensure dependent questions are put into the
* correct state
*/
private void setupDependencies() {
for (QuestionGroupTab tab : mQuestionGroupTabs) {
tab.setupDependencies();
}
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
View view;
if (position < mQuestionGroupTabs.size()) {
view = mQuestionGroupTabs.get(position);// Already instantiated
loadTab(position);// Load tab state, if necessary
} else {
view = mSubmitTab;
}
container.addView(view, 0);
return view;
}
@Override
public CharSequence getPageTitle(int position) {
if (position < mQuestionGroups.size()) {
return mQuestionGroups.get(position).getHeading();
} else {
return mPager.getContext().getString(R.string.submitbutton);
}
}
@Override
public void destroyItem(ViewGroup container, int position, Object view) {
container.removeView((View) view);
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public int getCount() {
if (mSubmitTab != null) {
return mQuestionGroups.size() + 1;// Do not forget the submit tab
}
return mQuestionGroups.size();
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
if (position == mQuestionGroupTabs.size() && mSubmitTab != null) {
// Check all the tabs have been populated by now
int i = 0;
while (i < position) {
loadTab(i++);
}
mSubmitTab.refresh(checkInvalidQuestions());
}
}
@Override
public void onPageScrollStateChanged(int state) {
// EMPTY
}
/**
* Checks if all the mandatory questions (on all tabs) have responses
*/
private List<Question> checkInvalidQuestions() {
List<Question> invalidQuestions = new ArrayList<>();
for (QuestionGroupTab questionGroupTab : mQuestionGroupTabs) {
invalidQuestions.addAll(questionGroupTab.checkInvalidQuestions());
}
return invalidQuestions;
}
}