package edu.gui;
import edu.exceptions.EvaluationException;
import edu.nodes.QuestionType;
import edu.nodes.styles.Style;
import edu.parser.QL.nodes.question.Question;
import edu.parser.QLS.QLSVisitor;
import edu.parser.QLS.QuestionRetriever;
import edu.parser.QLS.nodes.AbstractNode;
import edu.parser.QLS.nodes.QLSIdentifier;
import edu.parser.QLS.nodes.Section;
import edu.parser.QLS.nodes.Stylesheet;
import edu.parser.QLS.nodes.statement.Default;
import edu.parser.QLS.nodes.statement.Page;
import edu.parser.QLS.nodes.statement.QLSQuestion;
import sun.reflect.generics.reflectiveObjects.NotImplementedException;
import javax.swing.*;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* Created by Steven Kok on 06/03/2015.
*/
public class Renderer implements QLSVisitor {
private final QuestionRetriever questionRetriever;
private final MainWindow mainWindow;
private final List<Question> questionsToRender;
private List<Default> globalDefaultStyles;
public Renderer(Observer questionState) {
questionsToRender = new ArrayList<>();
questionRetriever = new QuestionRetriever();
mainWindow = new MainWindow(questionState);
globalDefaultStyles = new ArrayList<>();
}
public void render(List<Question> inputQuestions, Stylesheet stylesheet) {
this.globalDefaultStyles = stylesheet.getGlobalDefaultStatements();
initialize(inputQuestions, stylesheet);
SwingUtilities.invokeLater(mainWindow::showMainWindow);
mainWindow.goToSpecificPage(mainWindow.getCurrentPage());
}
public void reRender(List<Question> inputQuestions, Stylesheet stylesheet) {
initialize(inputQuestions, stylesheet);
mainWindow.goToSpecificPage(mainWindow.getCurrentPage());
}
private void initialize(List<Question> inputQuestions, Stylesheet stylesheet) {
this.questionsToRender.clear();
mainWindow.initialize();
storeQuestionsFromStylesheet(inputQuestions, stylesheet);
stylesheet.accept(this);
renderRemainingQuestions(inputQuestions);
}
private List<Question> getRemainingQuestions(List<Question> inputQuestions) {
return inputQuestions.stream()
.filter(inputQuestion -> !questionsToRender.contains(inputQuestion))
.collect(Collectors.toList());
}
private void renderRemainingQuestions(List<Question> inputQuestions) {
List<Question> remainingQuestions = getRemainingQuestions(inputQuestions);
List<QLSQuestion> convertedQuestions = convertQuestions(remainingQuestions);
ArrayList<Section> sections = createSection(convertedQuestions);
Page pageWithRemainingQuestions = new Page(sections);
addPage(pageWithRemainingQuestions, remainingQuestions);
}
private List<QLSQuestion> convertQuestions(List<Question> remainingQuestions) {
return remainingQuestions.stream()
.map(remainingQuestion -> new QLSQuestion(new QLSIdentifier(remainingQuestion.getQLIdentifier().getIdentifier()), remainingQuestion.getStyles()))
.collect(Collectors.toList());
}
private ArrayList<Section> createSection(List<QLSQuestion> convertedQuestions) {
Section section = new Section("Other", convertedQuestions, globalDefaultStyles);
ArrayList<Section> sections = new ArrayList<>();
sections.add(section);
return sections;
}
private void storeQuestionsFromStylesheet(List<Question> inputQuestions, Stylesheet stylesheet) {
List<QLSQuestion> stylesheetQuestions = extractQuestionsFromStylesheet(stylesheet);
stylesheetQuestions.stream()
.forEach(stylesheetQuestion -> storeQuestion(stylesheetQuestion, inputQuestions));
}
private List<QLSQuestion> extractQuestionsFromStylesheet(Stylesheet stylesheet) {
return questionRetriever.retrieveQuestions(stylesheet);
}
private void storeQuestion(QLSQuestion stylesheetQuestion, List<Question> inputQuestions) {
List<Question> question = inputQuestions.stream()
.filter(inputQuestion -> inputQuestion.getQLIdentifier().getIdentifier().equals(stylesheetQuestion.getQLSIdentifier().getIdentifier()))
.collect(Collectors.toList());
if (question.size() > 1) {
throw new EvaluationException("Stylesheet contains duplicates.");
} else if (!question.isEmpty()) {
storeQuestionWithStyle(question.get(0), stylesheetQuestion);
}
}
private void storeQuestionWithStyle(Question inputQuestion, QLSQuestion qlsQuestion) {
inputQuestion.setStyles(qlsQuestion.getStyles());
this.questionsToRender.add(inputQuestion);
}
private void visitStatements(Stylesheet stylesheet) {
stylesheet.getPages()
.stream()
.forEach(statement -> statement.accept(this));
}
@Override
public AbstractNode visit(Stylesheet stylesheet) {
visitStatements(stylesheet);
return stylesheet;
}
@Override
public AbstractNode visit(Page page) {
addPage(page, questionsToRender);
return page;
}
private void addPage(Page page, List<Question> questionsToRender) {
List<Section> sections = collectSections(page);
mainWindow.addPage(sections, questionsToRender);
}
private List<Section> collectSections(Page page) {
return page.getSections()
.stream()
.map(section -> (Section) section.accept(this))
.collect(Collectors.toList());
}
@Override
public AbstractNode visit(QLSQuestion question) {
return question;
}
@Override
public AbstractNode visit(QLSIdentifier QLSIdentifier) {
throw new NotImplementedException();
}
@Override
public AbstractNode visit(Section section) {
return section;
}
@Override
public AbstractNode visit(Default aDefault) {
return aDefault;
}
@Override
public AbstractNode visit(QuestionType questionType) {
return questionType;
}
@Override
public AbstractNode visit(Style style) {
return style;
}
}