package net.sf.egonet.web.panel;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeSet;
import net.sf.egonet.model.Question;
import net.sf.egonet.model.QuestionOption;
import net.sf.egonet.model.Study;
import net.sf.egonet.model.Answer.AnswerType;
import net.sf.egonet.model.Question.QuestionType;
import net.sf.egonet.persistence.DB;
import net.sf.egonet.persistence.Options;
import net.sf.egonet.persistence.Questions;
import net.sf.egonet.persistence.Studies;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.AjaxFallbackLink;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.markup.html.panel.EmptyPanel;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.PropertyModel;
import org.joda.time.DateTime;
import com.google.common.collect.Sets;
import com.google.common.collect.TreeMultiset;
public class EditStudyQuestionsPanel extends Panel {
private Long studyId;
private Question.QuestionType questionType;
private Form questionsContainer;
private Form editQuestionPanelContainer;
private Panel editQuestionPanel;
private TreeSet<Question> selectedQuestions;
public EditStudyQuestionsPanel(String id, Study study, Question.QuestionType questionType) {
super(id);
this.studyId = study.getId();
this.questionType = questionType;
build();
}
public Study getStudy() {
return Studies.getStudy(studyId);
}
private ArrayList<Question> questions;
private DateTime questionsLastRefreshed;
public List<Question> getQuestions() {
DateTime now = new DateTime();
if(questions == null || questionsLastRefreshed.isBefore(now.minusSeconds(1))) {
questions =
new ArrayList<Question>(Questions.getQuestionsForStudy(studyId,questionType));
questionsLastRefreshed = now;
}
return questions;
}
private TreeMultiset<Long> optionsPerQuestionId;
private DateTime optionsPerQuestionIdLastRefreshed;
private Integer getNumOptionsForQuestion(Question question) {
DateTime now = new DateTime();
if(optionsPerQuestionId == null ||
optionsPerQuestionIdLastRefreshed.isBefore(now.minusSeconds(1)))
{
optionsPerQuestionId = TreeMultiset.create();
for(QuestionOption option : Options.getOptionsForStudy(studyId)) {
optionsPerQuestionId.add(option.getQuestionId());
}
optionsPerQuestionIdLastRefreshed = now;
}
Integer numOptions = optionsPerQuestionId.count(question.getId());
return numOptions == null ? 0 : numOptions;
}
private void build()
{
selectedQuestions = new TreeSet<Question>();
questionsContainer = new Form("questionsContainer");
questionsContainer.setOutputMarkupId(true);
questionsContainer.add(new Label("caption",questionType+" Questions"));
ListView questions = new ListView("questions", new PropertyModel(this,"questions"))
{
protected void populateItem(final ListItem item) {
final Question question = (Question) item.getModelObject();
item.setOutputMarkupId(true);
final PanelContainer editor = new PanelContainer("editor");
editor.setOutputMarkupId(true);
item.add(editor);
Link questionLink = new AjaxFallbackLink("questionLink")
{
public void onClick(AjaxRequestTarget target) {
if(editor.isEmpty()) {
editor.changePanel(
new EditQuestionPanel("panel",
questionsContainer, question, questionType, studyId));
} else {
editor.removePanel();
}
target.addComponent(editor);
}
};
final Boolean selectionQuestion =
question.getAnswerType().equals(AnswerType.SELECTION) ||
question.getAnswerType().equals(AnswerType.MULTIPLE_SELECTION);
Link questionOptionsLink = new AjaxFallbackLink("questionOptionsLink") {
public void onClick(AjaxRequestTarget target) {
if(selectionQuestion) {
editor.changePanel(
new EditQuestionOptionsPanel("panel",
item,question));
target.addComponent(editor);
}
}
};
String questionTitle = question.getTitle();
questionLink.add(new Label("questionTitle",
questionTitle == null || questionTitle.trim().isEmpty() ? "__*__" :
questionTitle));
item.add(questionLink);
questionOptionsLink.add(
new Label("questionOptionsLabel",
selectionQuestion ?
"Options ("+
getNumOptionsForQuestion(question)+")"
: ""));
item.add(questionOptionsLink);
item.add(new Label("questionPrompt", question.getPrompt()));
item.add(new Label("questionResponseType", question.getAnswerType().toString()));
AjaxFallbackLink questionPreview = new AjaxFallbackLink("questionPreview") {
public void onClick(AjaxRequestTarget target) {
editor.changePanel(InterviewingPanel.createExample("panel", question));
target.addComponent(editor);
}
};
item.add(questionPreview);
if(QuestionType.EGO_ID.equals(question.getType())) {
questionPreview.setVisible(false);
}
item.add(new AjaxFallbackLink("questionDuplicate") {
public void onClick(AjaxRequestTarget target) {
Question newQ = question.copy();
newQ.setOrdering(
question.getOrdering() == null ? 0 :
question.getOrdering()+1);
List<Question> questions =
Questions.getQuestionsForStudy(studyId, question.getType());
int qIndex = questions.indexOf(question);
questions.add(qIndex+1, newQ);
for(int i = qIndex; i < questions.size(); i++) {
questions.get(i).setOrdering(i);
DB.save(questions.get(i));
}
for(QuestionOption option : Options.getOptionsForQuestion(question.getId())) {
Options.addOption(newQ, option.getName(), option.getValue());
}
target.addComponent(questionsContainer);
}
});
item.add(new AjaxFallbackLink("questionMoveUp") {
public void onClick(AjaxRequestTarget target) {
Questions.moveEarlier(question);
target.addComponent(questionsContainer);
}
});
Link questionSelectLink = new AjaxFallbackLink("questionSelect") {
public void onClick(AjaxRequestTarget target) {
if(selectedQuestions.contains(question)) {
selectedQuestions.remove(question);
} else {
selectedQuestions.add(question);
}
target.addComponent(questionsContainer);
}
};
questionSelectLink.add(new Label("questionSelectLabel",
selectedQuestions.contains(question) ? "[SELECTED]" : "Select"));
item.add(questionSelectLink);
item.add(new AjaxFallbackLink("questionPull") {
public void onClick(AjaxRequestTarget target) {
Questions.pull(question, selectedQuestions);
selectedQuestions = Sets.newTreeSet();
target.addComponent(questionsContainer);
}
});
item.add(new AjaxFallbackLink("questionDelete") {
public void onClick(AjaxRequestTarget target) {
Questions.delete(question);
EmptyPanel empty = new EmptyPanel("editQuestionPanel");
editQuestionPanel.replaceWith(empty);
editQuestionPanel = empty;
target.addComponent(questionsContainer);
target.addComponent(editQuestionPanelContainer);
}
});
}
};
questionsContainer.add(questions);
questionsContainer.add(new AjaxFallbackLink("newQuestion") {
public void onClick(AjaxRequestTarget target) {
editQuestion(new Question());
target.addComponent(editQuestionPanelContainer);
}
});
add(questionsContainer);
editQuestionPanelContainer = new Form("editQuestionPanelContainer");
editQuestionPanelContainer.setOutputMarkupId(true);
editQuestionPanel = new EmptyPanel("editQuestionPanel");
editQuestionPanelContainer.add(editQuestionPanel);
add(editQuestionPanelContainer);
}
private void editQuestion(Question question) {
Panel newPanel = new EditQuestionPanel("editQuestionPanel", questionsContainer, question, questionType, studyId);
editQuestionPanel.replaceWith(newPanel);
editQuestionPanel = newPanel;
}
}