
/************************************************
 * Includes
 */
 const clock_info = require("clock_info");
 const storage = require('Storage');
 const locale = require('locale');

/*
 * Some vars
 */
var W = g.getWidth();
var H = g.getHeight();

 /************************************************
  * Settings
  */
 const SETTINGS_FILE = "linuxclock.setting.json";
 let settings = {
   menuPosX: 0,
   menuPosY: 0,
 };

 let saved_settings = storage.readJSON(SETTINGS_FILE, 1) || settings;
 for (const key in saved_settings) {
   settings[key] = saved_settings[key]
 }


 /************************************************
  * Assets
  */
  Graphics.prototype.setFontUbuntuMono = function(scale) {
   // Actual height 24 (27 - 4)
   this.setFontCustom(
     atob(' '),
     32,
     atob("Dg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4c"),
     28+(scale<<8)+(1<<16)
   );
   return this;
 }



 /************************************************
  * Menu
  */
 var dateMenu = {
   name: "date",
   img: null,
   items: [
     { name: "time",
     get: () => ({ text: getTime(), img: null}),
     show: function() {},
     hide: function () {}
   },
   { name: "day",
    get: () => ({ text: getDay(), img: null}),
    show: function() {},
    hide: function () {}
   },
   { name: "date",
     get: () => ({ text: getDate(), img: null}),
     show: function() {},
     hide: function () {}
   },
   { name: "week",
     get: () => ({ text: weekOfYear(), img: null}),
     show: function() {},
     hide: function () {}
   },
   ]
 };

 var menu = clock_info.load();
 menu = menu.concat(dateMenu);

 // Ensure that our settings are still in range (e.g. app uninstall). Otherwise reset the position it.
 if(settings.menuPosX >= menu.length || settings.menuPosY > menu[settings.menuPosX].items.length ){
   settings.menuPosX = 0;
   settings.menuPosY = 0;
 }

function canRunMenuItem(){
  var menuEntry = menu[settings.menuPosX];
  var item = menuEntry.items[settings.menuPosY];
  return item.run !== undefined;
}


function runMenuItem(){
  var menuEntry = menu[settings.menuPosX];
  var item = menuEntry.items[settings.menuPosY];
  try{
    var ret = item.run();
    if(ret){
      Bangle.buzz(300, 0.6);
    }
  } catch (ex) {
    // Simply ignore it...
  }
}

/************************************************
* Helper
*/
function getTime(){
  var date = new Date();
  return twoD(date.getHours())+ ":" + twoD(date.getMinutes());
}

function getDate(){
  var date = new Date();
  return twoD(date.getDate()) + "." + twoD(date.getMonth());
}

function getDay(){
  var date = new Date();
  return locale.dow(date, true);
}

function weekOfYear() {
  var date = new Date();
  date.setHours(0, 0, 0, 0);
  // Thursday in current week decides the year.
  date.setDate(date.getDate() + 3 - (date.getDay() + 6) % 7);
  // January 4 is always in week 1.
  var week1 = new Date(date.getFullYear(), 0, 4);
  // Adjust to Thursday in week 1 and count number of weeks from date to week1.
  return 1 + Math.round(((date.getTime() - week1.getTime()) / 86400000
                        - 3 + (week1.getDay() + 6) % 7) / 7);
}



/************************************************
* Draw
*/
function draw() {
  queueDraw();

  g.setFontUbuntuMono();
  g.setFontAlign(-1, -1);

  g.clearRect(0,24,W,H);

  drawMainScreen();
}



function drawMainScreen(){
  // Get menu item based on x
  var menuItem = menu[settings.menuPosX];
  var cmd = menuItem.name.slice(0,5).toLowerCase();
  drawCmd(cmd);

  // Draw menu items depending on our y value
  drawMenuItems(menuItem);

  // And draw the cursor
  drawCursor();
}

function drawMenuItems(menuItem) {
  var start = parseInt(settings.menuPosY / 4) * 4;
  for (var i = start; i < start + 4; i++) {
    if (i >= menuItem.items.length) {
      continue;
    }

    var item = menuItem.items[i];
    drawText(item.name, item.get().text, (i%4)+1);
  }
}

function drawCursor(){
  g.setFontUbuntuMono();
  g.setFontAlign(-1, -1);
  g.setColor(g.theme.fg);

  g.clearRect(0, 27 + 28, 15, H);
  if(!Bangle.isLocked()){
    g.drawString(">", -2, ((settings.menuPosY % 4) + 1) * 27 + 28);
  }
}

function drawText(key, value, line){
  var x = 15;
  var y = line * 27 + 28;

  g.setFontUbuntuMono();
  g.setFontAlign(-1, -1);
  g.setColor(g.theme.fg);

  if(key){
    key = (key.toLowerCase() + "    ").slice(0, 4) + "|";
  } else {
    key = ""
  }

  value = String(value).replace("\n", " ");
  g.drawString(key + value, x, y);

}


function drawCmd(cmd){
  var c = 0;
  var x = 10;
  var y = 28;

  g.setColor("#0f0");
  g.drawString("bjs", x+c, y);
  c += g.stringWidth("bjs");

  g.setColor(g.theme.fg);
  g.drawString(":", x+c, y);
  c += g.stringWidth(":");

  g.setColor("#0ff");
  g.drawString("$ ", x+c, y);
  c += g.stringWidth("$ ");

  g.setColor(g.theme.fg);
  g.drawString(cmd, x+c, y);
}

function twoD(str){
  return ("0" + str).slice(-2)
}


/************************************************
* Listener
*/
// timeout used to update every minute
var drawTimeout;

// schedule a draw for the next minute
function queueDraw() {
  if (drawTimeout) clearTimeout(drawTimeout);
  drawTimeout = setTimeout(function() {
    drawTimeout = undefined;
    draw();
  }, 60000 - (Date.now() % 60000));
}


// Stop updates when LCD is off, restart when on
Bangle.on('lcdPower',on=>{
  if (on) {
    draw(); // draw immediately, queue redraw
  } else { // stop draw timer
    if (drawTimeout) clearTimeout(drawTimeout);
    drawTimeout = undefined;
  }
});


Bangle.on('lock', function(isLocked) {
  drawCursor();
});


Bangle.on('charging',function(charging) {
  if (drawTimeout) clearTimeout(drawTimeout);
  drawTimeout = undefined;

  settings.menuPosX=0;
  settings.menuPosY=0;

  draw();
});


Bangle.on('touch', function(btn, e){
  var left = parseInt(g.getWidth() * 0.22);
  var right = g.getWidth() - left;
  var upper = parseInt(g.getHeight() * 0.22) + 20;
  var lower = g.getHeight() - upper;

  var is_upper = e.y < upper;
  var is_lower = e.y > lower;
  var is_left = e.x < left && !is_upper && !is_lower;
  var is_right = e.x > right && !is_upper && !is_lower;
  var is_center = !is_upper && !is_lower && !is_left && !is_right;

  var oldYScreen = parseInt(settings.menuPosY/4);
  if(is_lower){
    if(settings.menuPosY >= menu[settings.menuPosX].items.length-1){
    return;
    }

    Bangle.buzz(40, 0.6);
    settings.menuPosY++;
    if(parseInt(settings.menuPosY/4) == oldYScreen){
    drawCursor();
    return;
    }
  }

  if(is_upper){
    if(e.y < 20){ // Reserved for widget clicks
      return;
    }

    if(settings.menuPosY <= 0){
    return;
    }
    Bangle.buzz(40, 0.6);
    settings.menuPosY--;
    settings.menuPosY = settings.menuPosY < 0 ? 0 : settings.menuPosY;

    if(parseInt(settings.menuPosY/4) == oldYScreen){
    drawCursor();
    return;
    }
  }

  if(is_right){
    Bangle.buzz(40, 0.6);
    settings.menuPosX = (settings.menuPosX+1) % menu.length;
    settings.menuPosY = 0;
  }

  if(is_left){
    Bangle.buzz(40, 0.6);
    settings.menuPosY = 0;
    settings.menuPosX  = settings.menuPosX-1;
    settings.menuPosX = settings.menuPosX < 0 ? menu.length-1 : settings.menuPosX;
  }

  if(is_center){
  if(!canRunMenuItem()){
    return;
  }
  runMenuItem();
  }

  draw();
});

E.on("kill", function(){
  try{
    storage.write(SETTINGS_FILE, settings);
  } catch(ex){
    // If this fails, we still kill the app...
  }
});


/************************************************
* Startup Clock
*/
// Show launcher when middle button pressed
Bangle.setUI("clock");

// Load and draw widgets
Bangle.loadWidgets();
Bangle.drawWidgets();

// Draw first time
draw();
