package edu.neu.ccs.task.web;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import javax.xml.stream.XMLStreamException;
import webframe.CauseOfDeath;
import webframe.Command;
import webframe.DialogueSession;
import edu.neu.ccs.task.Plan;
import edu.neu.ccs.task.Slot;
import edu.neu.ccs.task.Task;
import edu.neu.ccs.task.agent.Agent;
import edu.neu.ccs.task.dialogue.Display;
import edu.neu.ccs.task.util.Pair;
class DTaskSession implements DialogueSession {
private final Agent agent;
private final int user;
private final Persistence persistence;
private Command output;
private boolean didDisplay = false;
private List<Pair<String, Integer>> inputs;
private boolean closed = false;
public DTaskSession(Agent agent, int user, Persistence persistence) {
this.agent = agent;
this.user = user;
this.persistence = persistence;
this.output = Command.clearPage();
}
public void performComplete(List<String> warnings) throws IOException {
System.out.println("performComplete");
if (! agent.isLive()) return;
if (!agent.hasCurrentTurn())
advanceTurn();
else {
if (!didDisplay && (agent.getCurrentDisplay() != null)) {
didDisplay = true;
if (doSpeech())
return;
}
List<Pair<String, Integer>> inputs = agent.getCurrentInputs();
if (inputs != null) {
doMenu(inputs);
return;
}
String prompt = agent.getCurrentInputPrompt();
if (prompt != null) {
doTextInput(prompt);
return;
}
Pair<String, Map<String, String>> widget = agent.getCurrentInputWidget();
if (widget != null) {
doWidgetInput(widget);
return;
}
// this turn is output-only (no input of any kind):
agent.applyCurrentTurn();
advanceTurn();
}
}
public void error(String err) throws Exception {
System.out.println("error: " + err);
if (! agent.isLive()) return;
if (agent.hasCurrentTurn())
agent.failCurrentTurn();
advanceTurn();
}
public void menuInput(int index) throws IOException {
System.out.println("menuInput");
if (! agent.isLive()) return;
if (inputs == null) return;
int choice = inputs.get(index).second;
if (choice < 0)
output = Command.speech(agent.getCurrentAnnotatedAltOutput());
else {
agent.applyCurrentTurn(choice);
advanceTurn();
}
}
public void textInput(String text) throws IOException {
System.out.println("textInput");
if (! agent.isLive()) return;
agent.applyCurrentTurn(text);
advanceTurn();
}
public void widgetInput(String text) throws IOException {
System.out.println("widgetInput");
if (! agent.isLive()) return;
agent.applyCurrentTurn(text);
advanceTurn();
}
public void timeout() throws IOException {
System.out.println("timeout");
if ( ! agent.isLive()) return;
// TODO bail on conversation after multiple user timeouts?
if (inputs != null) {
String speech = agent.getCurrentAnnotatedAltOutput();
if (speech != null)
output = Command.speech(speech);
}
}
private void advanceTurn() throws IOException {
System.out.println("advanceTurn");
inputs = null;
didDisplay = false;
while (agent.isLive()) {
if (agent.nextTurn()) {
Display d = agent.getCurrentDisplay();
if (d != null) {
String url = d.getUrl(agent.getFocusTask());
output = Command.page(url, d.getType(), d.getSize(), d.isAuth());
return;
}
if (doSpeech())
return;
doMenu(agent.getCurrentInputs());
return;
}
}
String exitUrl = null;
Plan top = agent.getTop();
Task topTask = top.getThisTask();
Slot exitUrlSlot = topTask.getType().getSlotIfExists("exitUrl");
if ((exitUrlSlot != null) &&
exitUrlSlot.isOutput() &&
"string".equals(exitUrlSlot.getType()) &&
topTask.isDefinedSlot("exitUrl")) {
Object exitUrlObj = topTask.getSlotValue("exitUrl");
if (exitUrlObj != null)
exitUrl = exitUrlObj.toString();
}
output = Command.exit("finished", exitUrl);
}
private boolean doSpeech() {
System.out.println("doSpeech");
String speech = agent.getCurrentAnnotatedOutput();
if (speech == null) return false;
output = Command.speech(speech);
return true;
}
private void doMenu(List<Pair<String, Integer>> inputs) {
System.out.println("doMenu");
this.inputs = inputs;
List<String> items = new ArrayList<String>(inputs.size());
for (Pair<String, Integer> input : inputs)
items.add(input.first);
output = Command.menu(Command.NO_TIMEOUT, items);
}
private void doTextInput(String prompt) {
System.out.println("doTextInput");
output = Command.freeText(Command.NO_TIMEOUT, prompt);
}
private void doWidgetInput(Pair<String, Map<String,String>> w) {
System.out.print("doWidgetInput");
output = Command.widget(Command.NO_TIMEOUT, w.first, w.second);
}
public Command output() {
return output;
}
public void close(CauseOfDeath cause) throws Exception {
if (closed) return;
closed = true;
if (agent.isLive())
output = Command.exit("client quit");
persistence.save(agent, user);
}
public boolean status(HttpServletResponse resp, String type,
Map<String, String[]> params) throws XMLStreamException,
IOException {
resp.setContentType("text/xml");
resp.setCharacterEncoding("UTF-8");
return agent.status(resp.getWriter(), type);
}
public boolean action(HttpServletResponse resp, String type,
Map<String, String[]> params) {
return false;
}
}