            [org.commcare.util.cli MenuScreen EntityScreen]
            [org.commcare.core.parse ParseUtils]
            [org.javarosa.core.util.externalizable LivePrototypeFactory]
+           [org.javarosa.core.services.locale Localization]
            [org.javarosa.core.services.storage StorageManager]
            [org.javarosa.core.model.instance FormInstance]
            [org.commcare.session SessionFrame]

(defn get-next-screen [session]
  (let [eval-context (.getEvaluationContext session)
        needed (.getNeededData session eval-context)]
    (cond 
      (nil? needed) nil
      (= needed SessionFrame/STATE_COMMAND_ID) (MenuScreen.)
      (= needed SessionFrame/STATE_DATUM_VAL) (EntityScreen.)
      (= needed SessionFrame/STATE_DATUM_COMPUTED)
      (do 
        (.setComputedDatum session)
        (recur session))
      :else (throw (RuntimeException. "Unexpected frame request")))))

(defn clear-view []
  (map (fn [x] (println "\n")) (range 5)))

(defn process-command [command]
  (cond
    ((= command ":exit") 
(defn process-screen [screen app] 
  (clear-view)
  (.getWrappedDisplaytitle screen (:sandbox app) (.getPlatform (:engine app)))
  (.prompt screen System/out)
  (let [user-input (read-line)]
    (if (string/starts-with? user-input ":")
      (if (process-command user-input)
        true ;;; XXX I'm here
        (recur screen app))
      (when 
        ; TODO: handle commands
        (.handleInputAndUpdateSession screen (:session app) user-input)
        (recur screen app))))

(defn form-entry []
  (println "TODO form entry"))


(defrecord App [session engine sandbox])

(defn long-str [& strings] (string/join "\n" strings))
(def ^:const
  HELP_MESSAGE
  (long-str
    ":exit / :quit - Terminate the session and close the CLI app"
    ":update (-f) - Update the application live against the newest version on the server. -f optional flag to grab the newest build instead of the newest starred build"
    ":home - Navigate to the home menu of the app"
    ":lang <lang> - change the language to <lang> (e.g. :lang en)"
    ":stack - Show the current session frame stack"))

(defn build-user-sandbox [prototype-factory restore-file]
  (let [sandbox (MockUserDataSandbox. prototype-factory)
        restore (try (BufferedInputStream. (FileInputStream. restore-file))
                     (catch FileNotFoundException e
                       (println "No restore file found at " restore-file)))]
    (.setAppFixtureStorageLocation sandbox (StorageManager/getStorage FormInstance/STORAGE_KEY))
    (ParseUtils/parseIntoSandbox restore sandbox, false)
