const app = "drained";

// from boot.js
declare let drainedInterval: IntervalId | undefined;
if(typeof drainedInterval !== "undefined")
  drainedInterval = clearInterval(drainedInterval) as undefined;

// backlight
Bangle.setLCDBrightness(0);

// peripherals
const powerNoop = () => false;

const forceOff = (name: "GPS" | "HRM" | "Compass" /*| "Barom"*/) => {
  if ((Bangle as any)._PWR?.[name])
    (Bangle as any)._PWR[name] = [];

  // if(name === "Barom"){ setBarometerPower(...) }
  //                               ^^^^
  Bangle[`set${name}Power`](0, app);
  Bangle[`set${name}Power`] = powerNoop;
};
forceOff("GPS");
forceOff("HRM");
try{
  NRF.disconnect();
  NRF.sleep();
}catch(e){
  console.log(`couldn't disable ble: ${e}`);
}

// events
Bangle.removeAllListeners();
clearWatch();

// UI
Bangle.setOptions({
  wakeOnFaceUp: 0,
  wakeOnTouch: 0,
  wakeOnTwist: 0,
});

// clock
let nextDraw: TimeoutId | undefined;
const draw = () => {
  const x = g.getWidth() / 2;
  const y = g.getHeight() / 2 - 48;

  const date = new Date();

  const timeStr = require("locale").time(date, 1);
  const dateStr = require("locale").date(date, 0).toUpperCase() +
    "\n" +
    require("locale").dow(date, 0).toUpperCase();
  const x2 = x + 6;
  const y2 = y + 66;
  const charging = Bangle.isCharging();

  g.reset()
    .clearRect(Bangle.appRect)
    .setFont("Vector", 55)
    .setFontAlign(0, 0)
    .setColor(charging ? "#0f0" : g.theme.fg)
    .drawString(timeStr, x, y)
    .setFont("Vector", 24)
    .drawString(dateStr, x2, y2);

  if(charging)
    g.drawString(`charging: ${E.getBattery()}%`, x2, y2 + 48);
  else
    g.drawString(`${E.getBattery()}%`, x2, y2 + 48);

  if(nextDraw) clearTimeout(nextDraw);
  nextDraw = setTimeout(() => {
    nextDraw = undefined;
    draw();
  }, 60000 - (date.getTime() % 60000));
};

const reload = () => {
  let scroller: MenuInstance["scroller"] | undefined;
  const showMenu = () => {
    const menu: Menu = {
      "Restore to full power": drainedRestore,
    };

    if (NRF.getSecurityStatus().advertising)
      menu["Disable BLE"] = () => { NRF.sleep(); showMenu(); };
    else
      menu["Enable BLE"] = () => { NRF.wake(); showMenu(); };

    menu["Settings"] = () => load("setting.app.js");
    menu["Recovery"] = () => Bangle.showRecoveryMenu();
    menu["Exit menu"] = reload;

    if(scroller){
      menu[""] = { selected: scroller.scroll };
    }

    if(nextDraw) clearTimeout(nextDraw);
    ({ scroller } = E.showMenu(menu));
  };

  Bangle.setUI({
    mode: "custom",
    remove: () => {
      if (nextDraw) clearTimeout(nextDraw);
      nextDraw = undefined;
    },
    btn: showMenu
  });
  Bangle.CLOCK=1;

  g.clear();
  draw();
};
reload();

// permit other apps to put themselves into low-power mode
Bangle.emit("drained", E.getBattery());

// restore normal boot on charge
const { keepStartup = true, restore = 20, exceptions = ["widdst.0"], interval = 10 }: DrainedSettings
  = require("Storage").readJSON(`${app}.setting.json`, true) || {};

// re-enable normal boot code when we're above a threshold:
function drainedRestore() { // "public", to allow users to call
  if(!keepStartup){
    try{
      eval(require('Storage').read('bootupdate.js'));
    }catch(e){
      console.log("error restoring bootupdate:" + e);
    }
  }
  load(); // necessary after updating boot.0
}

const checkCharge = () => {
  if(E.getBattery() < restore) {
    draw();
    return;
  }
  drainedRestore();
};

if (Bangle.isCharging())
  checkCharge();

Bangle.on("charging", charging => {
  if(drainedInterval)
    drainedInterval = clearInterval(drainedInterval) as undefined;
  if(charging)
    drainedInterval = setInterval(checkCharge, interval * 60 * 1000);
  draw(); // redraw to update charging status on screen
});

if(!keepStartup){
  const storage = require("Storage");
  for(const boot of exceptions){
    try{
      const js = storage.read(`${boot}.boot.js`);
      if(js) eval(js);
    }catch(e){
      console.log(`error loading boot exception "${boot}": ${e}`);
    }
  }
}
