/* eslint-disable no-undef */
const Setter = {
  NONE: "none",
  UPPER: 'upper',
  LOWER: 'lower'
};
const SETTINGS_FILE = "wohrm.setting.json";
var settings = require('Storage').readJSON(SETTINGS_FILE, 1) || {
  upperLimit: 130,
  lowerLimit: 100
};

const shortBuzzTimeInMs = 80;
const longBuzzTimeInMs = 400;

let upperLimitChanged = true;
let lowerLimitChanged = true;

let limitSetter = Setter.NONE;

let currentHeartRate = 0;
let hrConfidence = -1;
let hrChanged = true;
let confidenceChanged = true;

let setterHighlightTimeout;

const isB1 = process.env.HWVERSION==1;
const upperLshape = isB1 ? {
  right: 125,
  left: 210,
  bottom: 40,
  top: 210,
  rectWidth: 30,
  cornerRoundness: 5,
  orientation: -1,
  color: '#f00'
} : {
  right: Bangle.appRect.x2-100,
  left: Bangle.appRect.x2,
  bottom: 24,
  top: Bangle.appRect.y2,
  rectWidth: 26,
  cornerRoundness: 4,
  orientation: -1,   // rotated 180°
  color: '#f00'
};

const lowerLshape = {
  left: isB1 ? 10 : Bangle.appRect.x,
  right: 100,
  bottom: upperLshape.top,
  top: upperLshape.bottom,
  rectWidth: upperLshape.rectWidth,
  cornerRoundness: upperLshape.cornerRoundness,
  orientation: 1,
  color: '#00f'
};

const centerBar = {
  minY: (upperLshape.bottom + upperLshape.top - upperLshape.rectWidth)/2,
  maxY: (upperLshape.bottom + upperLshape.top + upperLshape.rectWidth)/2,
  confidenceWidth: isB1 ? 10 : 8,
  minX: isB1 ? 55 : upperLshape.rectWidth + 14,
  maxX: isB1 ? 165 : Bangle.appRect.x2 - upperLshape.rectWidth - 14
};

const fontSizes = isB1 ? {
  limits: 13,
  heartRate: 24
} : {
  limits: 12,
  heartRate: 20
};

function fillEllipse(x, y, x2, y2) {
  g.fillEllipse(Math.min(x, x2),
                Math.min(y, y2),
                Math.max(x, x2),
                Math.max(y, y2));
}

/**
 * @param p.left: the X coordinate of the left side of the L in its orientation
 * @param p.right: the X coordinate of the right side of the L in its orientation
 * @param p.top: the Y coordinate of the top side of the L in its orientation
 * @param p.bottom: the Y coordinate of the bottom side of the L in its orientation
 * @param p.strokeWidth: how thick we draw the letter.
 * @param p.cornerRoundness: how much the corners should be rounded
 * @param p.orientation: 1 == turned 0°; -1 == turned 180°
 * @param p.color: the color to draw the shape
 */
function renderLshape(p) {
  g.setColor(p.color);

  g.fillRect(p.right, p.bottom, p.left, p.bottom-p.orientation*p.rectWidth);
  g.fillRect(p.left+p.orientation*p.rectWidth,
             p.bottom-p.orientation*p.rectWidth,
             p.left,
             p.top+p.orientation*p.cornerRoundness*2);

  //Round end of small line
  fillEllipse(p.right+p.orientation*p.cornerRoundness*2,
              p.bottom,
              p.right-p.orientation*p.cornerRoundness*2,
              p.bottom-p.orientation*p.rectWidth);

  //Round outer corner
  g.setColor(g.theme.bg);
  g.fillRect(p.left+p.orientation*p.cornerRoundness,
             p.bottom,
             p.left,
             p.bottom-p.orientation*p.cornerRoundness);
  g.setColor(p.color);
  fillEllipse(p.left+p.orientation*p.cornerRoundness*4,
              p.bottom,
              p.left,
              p.bottom-p.orientation*p.cornerRoundness*2);

  //Round inner corner
  g.fillRect(p.left+p.orientation*(p.rectWidth+p.cornerRoundness+1),
             p.bottom-p.orientation*(p.rectWidth+1),
             p.left+p.orientation*(p.rectWidth+1),
             p.bottom-p.orientation*(p.rectWidth+p.cornerRoundness-1));
  g.setColor(g.theme.bg);
  fillEllipse(p.left+p.orientation*(p.rectWidth+p.cornerRoundness*4),
              p.bottom-p.orientation*(p.rectWidth+1),
              p.left+p.orientation*(p.rectWidth+1),
              p.bottom-p.orientation*(p.rectWidth+p.cornerRoundness*3-1));

  //Round end of long line
  g.setColor(p.color);
  fillEllipse(p.left+p.orientation*p.rectWidth,
              p.top+p.orientation*p.cornerRoundness*4,
              p.left,
              p.top);
}

function drawTrainingHeartRate() {
  //Only redraw if the display is on
  if (Bangle.isLCDOn()) {
    renderUpperLimit();

    renderCurrentHeartRate();

    renderLowerLimit();

    renderConfidenceBars();
  }

  buzz();
}

function renderUpperLimit() {
  if(!upperLimitChanged) { return; }

  renderLshape(upperLshape);

  if(limitSetter === Setter.UPPER){
    g.setColor(1,1,0);
  } else {
    g.setColor(g.theme.fg);
  }
  g.setFontVector(fontSizes.limits).setFontAlign(-1, 0, 0);
  g.drawString("Upper: " + settings.upperLimit,
               upperLshape.right,
               upperLshape.bottom+upperLshape.rectWidth/2);

  upperLimitChanged = false;
}

function renderCurrentHeartRate() {
  if(!hrChanged) { return; }

  g.setColor(g.theme.fg);
  g.fillRect(centerBar.minX, centerBar.minY,
             centerBar.maxX, centerBar.maxY);

  g.setColor(g.theme.bg);
  g.setFontVector(fontSizes.heartRate);
  g.setFontAlign(1, 0, 0);
  g.drawString(currentHeartRate,
               Math.max(upperLshape.right+upperLshape.cornerRoundness,
                        lowerLshape.right-lowerLshape.cornerRoundness),
               (centerBar.minY+centerBar.maxY)/2);

  //Reset alignment to defaults
  g.setFontAlign(-1, -1, 0);

  hrChanged = false;
}

function renderLowerLimit() {
  if(!lowerLimitChanged) { return; }

  renderLshape(lowerLshape);

  if(limitSetter === Setter.LOWER){
    g.setColor(1,1,0);
  } else {
    g.setColor(g.theme.fg);
  }
  g.setFontVector(fontSizes.limits).setFontAlign(-1, 0, 0);
  g.drawString("Lower: " + settings.lowerLimit,
               lowerLshape.left + lowerLshape.rectWidth/2,
               lowerLshape.bottom - lowerLshape.rectWidth/2);

  lowerLimitChanged = false;
}

function renderConfidenceBars(){
  if(!confidenceChanged) { return; }

  if(hrConfidence >= 85){
    g.setColor(0, 1, 0);
  } else if (hrConfidence >= 50) {
    g.setColor(1, 1, 0);
  } else if(hrConfidence >= 0){
    g.setColor(1, 0, 0);
  } else {
    g.setColor(g.theme.fg);
  }

  g.fillRect(centerBar.minX-centerBar.confidenceWidth, centerBar.minY, centerBar.minX, centerBar.maxY);
  g.fillRect(centerBar.maxX, centerBar.minY, centerBar.maxX+centerBar.confidenceWidth, centerBar.maxY);

  confidenceChanged = false;
}

function renderPlusMinusIcons() {
  if (limitSetter === Setter.NONE) {
    g.setColor(g.theme.bg);
  } else {
    g.setColor(g.theme.fg);
  }

  g.setFontVector(14);

  //+ for Btn1
  g.drawString("+", 222, 50);

  //- for Btn3
  g.drawString("-", 222,165);

  return;
}

function renderHomeIcon() {
  //Home for Btn2
  g.setColor(1, 1, 1);
  g.drawLine(220, 118, 227, 110);
  g.drawLine(227, 110, 234, 118);

  g.drawPoly([222,117,222,125,232,125,232,117], false);
  g.drawRect(226,120,229,125);
}

function buzz() {
  // Do not buzz if not confident
  if(hrConfidence < 85) { return; }

  if(currentHeartRate > settings.upperLimit)
  {
    Bangle.buzz(shortBuzzTimeInMs);
    setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs * 2);
  }

  if(currentHeartRate < settings.lowerLimit)
  {
    Bangle.buzz(longBuzzTimeInMs);
  }
}

function onHrm(hrm){
  if(currentHeartRate !== hrm.bpm){
    currentHeartRate = hrm.bpm;
    hrChanged = true;
  }

  if(hrConfidence !== hrm.confidence) {
    hrConfidence = hrm.confidence;
    confidenceChanged = true;
  }
}

function setLimitSetterToLower() {
  resetHighlightTimeout();

  limitSetter = Setter.LOWER;

  upperLimitChanged = true;
  lowerLimitChanged = true;

  renderUpperLimit();
  renderLowerLimit();
  renderPlusMinusIcons();
}

function setLimitSetterToUpper() {
  resetHighlightTimeout();

  limitSetter = Setter.UPPER;

  upperLimitChanged = true;
  lowerLimitChanged = true;

  renderLowerLimit();
  renderUpperLimit();
  renderPlusMinusIcons();
}

function setLimitSetterToNone() {
  limitSetter = Setter.NONE;

  upperLimitChanged = true;
  lowerLimitChanged = true;

  renderLowerLimit();
  renderUpperLimit();
  renderPlusMinusIcons();
}

function incrementLimit() {
  resetHighlightTimeout();

  if (limitSetter === Setter.UPPER) {
    settings.upperLimit++;
    renderUpperLimit();
    upperLimitChanged = true;
  } else if(limitSetter === Setter.LOWER) {
    settings.lowerLimit++;
    renderLowerLimit();
    lowerLimitChanged = true;
  }
}

function decrementLimit(){
  resetHighlightTimeout();

  if (limitSetter === Setter.UPPER) {
    settings.upperLimit--;
    renderUpperLimit();
    upperLimitChanged = true;
  } else if(limitSetter === Setter.LOWER) {
    settings.lowerLimit--;
    renderLowerLimit();
    lowerLimitChanged = true;
  }
}

function resetHighlightTimeout() {
  if (setterHighlightTimeout) {
    clearTimeout(setterHighlightTimeout);
  }

  setterHighlightTimeout = setTimeout(setLimitSetterToNone, 2000);
}

function switchOffApp(){
  Bangle.setHRMPower(0,"wohrm");
  load();
}

Bangle.on('lcdPower', (on) => {
  if (on) {
    Bangle.drawWidgets();

    if (typeof(BTN5) !== typeof(undefined)) {
      renderHomeIcon();
    }
    renderLshape(lowerLshape);
    renderLshape(upperLshape);
    lowerLimitChanged = true;
    upperLimitChanged = true;
    drawTrainingHeartRate();
  }
});

Bangle.setHRMPower(1,"wohrm");
Bangle.on('HRM', onHrm);

g.setTheme({bg:"#000",fg:"#fff",dark:true});
g.reset();
g.clear();
Bangle.loadWidgets();
Bangle.drawWidgets();

if (typeof(BTN5) !== typeof(undefined)) {
  renderHomeIcon();
  setWatch(incrementLimit, BTN1, {edge:"rising", debounce:50, repeat:true});
  setWatch(decrementLimit, BTN3, {edge:"rising", debounce:50, repeat:true});
  setWatch(setLimitSetterToLower, BTN4, {edge:"rising", debounce:50, repeat:true});
  setWatch(setLimitSetterToUpper, BTN5, { edge: "rising", debounce: 50, repeat: true });

  setWatch(switchOffApp, BTN2, {edge:"falling", debounce:50, repeat:true});
} else {
  setWatch(switchOffApp, BTN1, {edge:"falling", debounce:50, repeat:true});
}

setInterval(drawTrainingHeartRate, 1000);
