exports.reply = function (options) {
  var keyboard = "textinput";
  try {
    keyboard = require(keyboard);
  } catch (e) {
    keyboard = null;
  }

  function constructReply(msg, replyText, resolve, reject) {
    if (!replyText) { 
      reject("");
      return;
    }

    var responseMessage = {msg: replyText};
    if (msg.id) {
      responseMessage = { t: "notify", id: msg.id, n: "REPLY", msg: replyText };
    }
    E.showMenu();
    if (options.sendReply == null || options.sendReply) {
      Bluetooth.println(JSON.stringify(responseMessage));
    }
    resolve(responseMessage);
  }

  return new Promise((resolve, reject) => {
    var menu = {
      "": {
        title: options.title || /*LANG*/ "Reply with:",
        back: function () {
          E.showMenu();
          reject("User pressed back");
        },
      }, // options
      /*LANG*/ "Compose": function () {
        keyboard.input().then((result) => {
          if (result)
            constructReply(options.msg ?? {}, result, resolve, reject);
          else
            E.showMenu(menu);
        });
      },
    };
    var replies =
      require("Storage").readJSON(
        options.fileOverride || "replies.json",
        true
      ) || [];

    replies.forEach((reply) => {
      var displayString = reply.disp ?? reply.text;
      var wrappedDisplayString = g.wrapString(displayString, 120);
      // Generally handles truncating nicely, but falls down in long runs of emoji since they count as one image
      if (wrappedDisplayString.length > 1) {
        displayString = wrappedDisplayString[0]+"...";
      }
      menu = Object.defineProperty(menu, displayString, {
        value: () => constructReply(options.msg ?? {}, reply.text, resolve, reject),
      });
    });

    if (!keyboard) delete menu[/*LANG*/ "Compose"];

    if (replies.length == 0) {
      if (!keyboard) {
        E.showPrompt(
          /*LANG*/ "Please install a keyboard app, or set a custom reply via the app loader!",
          {
            buttons: { Ok: true },
            remove: function () {
              reject(
                "Please install a keyboard app, or set a custom reply via the app loader!"
              );
            },
          }
        );
      } else {
        keyboard.input().then((result) => {
          constructReply(options.msg, result, resolve, reject);
        });
      }
    } else{
      E.showMenu(menu);
    }
  });
};
