package com.klq.controller;
import com.klq.ast.impl.expr.AExpression;
import com.klq.ast.impl.expr.IdentifierNode;
import com.klq.ast.impl.value.UndefinedValue;
import com.klq.ast.impl.value.Value;
import com.klq.gui.IKLQItem;
import com.klq.gui.control.ARenderedQuestion;
import com.klq.gui.control.ComputedRenderedQuestion;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import org.antlr.v4.runtime.misc.NotNull;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* Created by Timon on 23.02.2015.
*/
public class Controller implements IKLQItem {
private final List<IdentifierNode> order;
private final Map<IdentifierNode, ARenderedQuestion> questionController;
private final VariableTable variableTable;
private final DoubleProperty progressProperty;
public Controller() {
order = new ArrayList<>();
questionController = new HashMap<>();
variableTable = new VariableTable();
progressProperty = new SimpleDoubleProperty(0);
}
public void add(ARenderedQuestion question) {
order.add(question.getID());
questionController.put(question.getID(), question);
variableTable.add(question.getID());
}
public List<ARenderedQuestion> getOrderedQuestions() {
List<ARenderedQuestion> result = new ArrayList<>();
for (IdentifierNode id : order) {
result.add(questionController.get(id));
}
return result;
}
public VariableTable getVariableTable() {
return variableTable;
}
public boolean dependenciesResolved(IdentifierNode questionId) {
assert questionController.containsKey(questionId): "All questions should be in the question store.";
ARenderedQuestion question = questionController.get(questionId);
return question.dependenciesResolved(variableTable);
}
public void updateAnswer(IdentifierNode questionId, @NotNull Value answer) {
variableTable.update(questionId, answer);
updateQuestionVisibilities();
updateComputedQuestions();
updateQuestionnaireProgress();
}
public void updateQuestionVisibilities(){
for (IdentifierNode id : questionController.keySet()){
boolean visible = dependenciesResolved(id);
ARenderedQuestion q = questionController.get(id);
if (q.isVisible() != visible) {
q.setVisible(visible);
}
}
}
private void updateComputedQuestions(){
Collection<ARenderedQuestion> questions = questionController.values();
questions.forEach(question -> {
if (question.isComputed()) {
ComputedRenderedQuestion crq = (ComputedRenderedQuestion) question;
AExpression computedExpression = crq.getComputedExpression();
Value result = computedExpression.evaluate(variableTable);
crq.updateComputedValue(result.toString());
variableTable.update(crq.getID(), result);
}
});
}
private void updateQuestionnaireProgress(){
double answered = 0;
double total = 0;
for (ARenderedQuestion q : questionController.values()){
if (!q.isComputed()){
total++;
Value v = variableTable.get(q.getID());
if (!v.equals(new UndefinedValue())){
answered++;
}
}
}
progressProperty.setValue(answered/total);
}
public DoubleProperty progressProperty(){
return progressProperty;
}
public boolean exportResults(String path){
DateFormat DATE_FORMAT = new SimpleDateFormat("dd-MM-yyyy_HH-mm-ss");
Date timestamp = new Date();
File file = new File(path + File.separator + DATE_FORMAT.format(timestamp) + ".xml");
try {
file.createNewFile();
String encoding = "UTF-8";
PrintWriter writer = new PrintWriter(file, encoding);
writer.write(String.format("<?xml version=\"1.0\" encoding=\"" + encoding + "\"?>%n"));
writer.write(String.format("<questionnaire>%n"));
for (IdentifierNode id : order) {
Value assignedValue = variableTable.get(id);
String varString = assignedValue.toString();
String xmlTag = String.format("\t<%s>%n" + "\t\t%s%n" + "\t</%s>%n",
id.getIdentifier(), varString, id.getIdentifier());
writer.write(xmlTag);
}
writer.write("</questionnaire>");
writer.flush();
writer.close();
} catch (FileNotFoundException fnf){
System.err.println(String.format("Could not write to file: %s", file));
return false;
} catch (IOException io){
System.err.println(String.format("Could not create file: %s", file));
return false;
}
return true;
}
}