(function(){
  const intervalLow = 60000; // update time when not charging
  const intervalHigh = 2000; // update time when charging

  let prevMin = 100;

  let COLORS = {};

  if (process.env.HWVERSION == 1) {
    COLORS = {
      'white':    -1,     // White
      'charging': 0x07E0, // Green
      'high':     0x05E0, // lightly darker green
      'ok':       0xFD20, // Orange
      'low':      0xF800, // Red
    };
  } else {
    // bangle 2 is only 7 bit colors
    COLORS = {
      'white':    "#fff", // White
      'charging': "#0f0", // Green
      'high':     "#0f0", // Green
      'ok':       "#ff0", // Orange
      'low':      "#f00", // Red
    };
  }
  const SETTINGS_FILE = 'widbatpc.json';

  let settings;
  function loadSettings() {
    settings = require('Storage').readJSON(SETTINGS_FILE, 1) || {};
    const DEFAULTS = {
      'color': 'By Level',
      'percentage': true,
      'charger': true,
      'hideifmorethan': 100,
      'alwaysoncharge': false,
      'removejitter': 0, // 0 == off, 1 == downwards only
      'buzzoncharge': true,
    };
    Object.keys(DEFAULTS).forEach(k=>{
      if (settings[k]===undefined) settings[k]=DEFAULTS[k];
    });
  }
  function setting(key) {
    if (!settings) { loadSettings(); }
    return settings[key];
  }

  const levelColor = (l) => {
  // "charging" is very bright -> percentage is hard to read, "high" is ok(ish)
    const green = setting('percentage') ? COLORS.high : COLORS.charging;
    switch (setting('color')) {
      case 'Monochrome': return COLORS.white; // no chance of reading the percentage here :-(
      case 'Green': return green;
      case 'By Level': // fall through
      default:
        if (setting('charger')) {
        // charger icon -> always make percentage readable
          if (Bangle.isCharging() || l >= 50) return green;
        } else {
        // no icon -> brightest green to indicate charging, even when showing percentage
          if (Bangle.isCharging()) return COLORS.charging;
          if (l >= 50) return COLORS.high;
        }
        if (l >= 15) return COLORS.ok;
        return COLORS.low;
    }
  };
  const chargerColor = () => {
    return (setting('color') === 'Monochrome') ? COLORS.white : COLORS.charging;
  };

  // sets width, returns true if it changed
  function setWidth() {
    var w = 40;
    if (Bangle.isCharging() && setting('charger'))
      w += 16;
    if (E.getBattery() > setting('hideifmorethan')) {
      w = 0;
      if( Bangle.isCharging() && setting('alwaysoncharge') === true)
        w = 56;
    }
    var changed = WIDGETS["batpc"].width != w;
    WIDGETS["batpc"].width = w;
    return changed;
  }

  function draw(fromInterval) {
  // if hidden, don't draw
    if (!WIDGETS["batpc"].width) return;
    // else...
    var s = 39;
    var x = this.x, y = this.y;
    let l = E.getBattery();
    if (setting('removejitter') === 1) {
      // if we have seen a battery percentage that was lower than current, use lower
      if (Bangle.isCharging()) {
        prevMin = l; // charging is the only way to increase percentage
      } else if (prevMin >= l) {
        prevMin = l;
      } else {
        l = prevMin;
      }
    }

    if (fromInterval === true && this.prevLevel === l && this.prevCharging === Bangle.isCharging()) {
      return; // unchanged, do nothing
    }

    this.prevLevel = l;
    this.prevCharging = Bangle.isCharging();

    const c = levelColor(l);

    if (Bangle.isCharging() && setting('charger')) {
      g.setColor(chargerColor()).drawImage(atob(
        "DhgBHOBzgc4HOP////////////////////3/4HgB4AeAHgB4AeAHgB4AeAHg"),x,y);
      x+=16;
    }

    let xl = x+4+l*(s-12)/100;
    // show bar full in the level color, as you can't see the color if the bar is too small
    if (setting('fillbar'))
      xl = x+4+100*(s-12)/100;

    g.setColor(g.theme.fg);
    g.fillRect(x,y+2,x+s-4,y+21);
    g.clearRect(x+2,y+4,x+s-6,y+19);
    g.fillRect(x+s-3,y+10,x+s,y+14);
    g.setColor(c).fillRect(x+4,y+6,xl,y+17);
    g.setColor(g.theme.fg);
    if (!setting('percentage')) {
      return;
    }
    let gfx = g;
    if (setting('color') === 'Monochrome') {
    // draw text inverted on battery level
      gfx = Graphics.createCallback(g.getWidth(),g.getHeight(), 1,
        (x,y) => {g.setPixel(x,y,x<=xl?0:-1);});
    }
    gfx.setFontAlign(-1,-1);
    if (l >= 100) {
      gfx.setFont('4x6', 2);
      gfx.drawString(l, x + 6, y + 7);
    } else {
      if (l < 10) x+=6;
      gfx.setFont('6x8', 2);
      gfx.drawString(l, x + 6, y + 4);
    }
  }

  // reload widget, e.g. when settings have changed
  function reload() {
    loadSettings();
    // need to redraw all widgets, because changing the "charger" setting
    // can affect the width and mess with the whole widget layout
    setWidth();
    g.clear();
    Bangle.drawWidgets();
  }

  // update widget - redraw just widget, or all widgets if size changed
  function update() {
    if (setWidth()) Bangle.drawWidgets();
    else WIDGETS["batpc"].draw();

    if (Bangle.isCharging()) changeInterval(id, intervalHigh);
      else                   changeInterval(id, intervalLow);
  }

  Bangle.on('charging',function(charging) {
    if (setting('buzzoncharge')) {
      if(charging) Bangle.buzz();
    }
    update();
    g.flip();
  });

  Bangle.on('lcdPower', function(on) {
    if (on) update();
  });

  var id = setInterval(()=>WIDGETS["batpc"].draw(true), intervalLow);

  WIDGETS["batpc"]={area:"tr",width:40,draw:draw,reload:reload};
  setWidth();
})();
