abstract sclass DynAskUserQuestions extends DynModule {
  S question, answer;
  bool speak, listen;
  transient JButton btnSubmit;
  transient S lastHeard;
  
  start {
    dm_onTopInput_q(voidfunc(S s) {
      if (listen) {
        if "next question" ret with newQuestion();
        if "no idea" { setField(answer := s); submit(); }
        if (isYes_1(s)) {
          submit();
          ret;
        }
        lastHeard = s;
        setField(answer := s);
        dm_showYesToAcceptPopupAbove(btnSubmit);
        dm_sayInEnglish(s);
      }
    });
  }
  
  visualize {
    if (empty(question)) newQuestion();
    JLabel lblQ = fontSizePlus(3, makeBold(dm_fieldLabel('question)));
    componentPopupMenuItem(lblQ, "Suggest question...", r {
      inputText("Question", question, voidfunc(S s) {
        setField(question := s)
      })
    });
    ret withRightMargin(makeForm2(
      "", withBottomMargin(15, lblQ),
      "Human answer:", centerAndEastWithMargin(onEnter(dm_fieldTextField('answer), rThread submit),
        btnSubmit = jbutton("Submit", rThread submit)),
      "", withBottomMargin(withTopMargin(20, rightAlignedButtons(
        dm_checkBox('listen), dm_checkBox('speak), "Ask me something else", rThread newQuestion)))));
  }
  
  abstract S makeAQuestion();
  
  void newQuestion enter {
    dm_hideYesPopupForComponent(btnSubmit);
    setFields(answer := "", question := makeAQuestion());
    if (empty(question)) ret with infoBox("Got nothing to ask");
    programLogStructure(litorderedmap(+question));
    vmBus_send('showingQuestion, module(), question);
    if (speak) dm_sayWithAutoLanguage_splitAtQuotes(question);
  }
  
  void submit enter {
    dm_hideYesPopupForComponent(btnSubmit);
    programLogStructure(litorderedmap(+question, +answer));
    vmBus_send('userAnsweredQuestion, module(), question, answer);
    dm_addQAndA(question, answer);
    infoBox(confirmationText());
    if (speak) dm_sayInEnglish(eq(lastHeard, answer) ? "confirmed" : answer);
    newQuestion();
  }
  
  S confirmationText() {
    ret "[saved] " + question + " => " + answer;
  }
}