// read in the faces
var FACES = [];
var STOR = require("Storage");
STOR.list(/\.kit\.js$/).forEach(face=>FACES.push(eval(require("Storage").read(face))));
var iface = STOR.list(/\.kit\.js$/).indexOf("stepo2.kit.js");
var face = FACES[iface]();
var firstPress
var pressTimer;

function stopdraw() {
  face.stopTimer();
}

function startdraw() {
  Bangle.drawWidgets();
  face.startTimer();
}

function nextFace(){
  stopdraw();
  face.freeResources();

  iface += 1
  iface = iface % FACES.length;
  face = FACES[iface]();

  g.clear();
  g.reset();
  face.init(gpsObj, swObj, hrmObj, tripObject);
  startdraw();
}

// when you feel the buzzer you know you have done a long press
function longPressCheck() {
  Bangle.buzz();
  debug_log("BUZZ, long press");
  if (pressTimer) {
    clearInterval(pressTimer);
    debug_log("CLEAR pressTimer 2");
    pressTimer = undefined;
  }
}

// start a timer and buzz when held long enough
function buttonPressed(btn) {
  if (btn === 3) {
    nextFace();
  } else {
    firstPress = getTime();
    if (pressTimer) {
      debug_log("CLEAR pressTimer 1");
      clearInterval(pressTimer);
    }
    debug_log("SET pressTimer 1");
    pressTimer = setInterval(longPressCheck, 1500);
  }
}

// if you release too soon there is no buzz as timer is cleared
function buttonReleased(btn) {
  var dur = getTime() - firstPress;
  if (pressTimer) {
    debug_log("CLEAR pressTimer 3");
    clearInterval(pressTimer);
    pressTimer = undefined;
  }

  if ( dur >= 1.5 ) {
    switch(btn) {
    case 1:
      face.onButtonLong(btn);
      break;
    case 2:
      face.onButtonLong(btn);
      //Bangle.showLauncher();
      break;
    case 3:
      // do nothing
      break;
    }
    return;
  }

  if (btn !== 3) face.onButtonShort(btn);
}

function setButtons(){
  setWatch(buttonPressed.bind(null,1), BTN1, {repeat:true,edge:"rising"});
  setWatch(buttonPressed.bind(null,2), BTN2, {repeat:true,edge:"rising"});
  setWatch(nextFace, BTN3, {repeat:true,edge:"rising"});

  setWatch(buttonReleased.bind(null,1), BTN1, {repeat:true,edge:"falling"});
  setWatch(buttonReleased.bind(null,2), BTN2, {repeat:true,edge:"falling"});
  // BTN 3 long press should always reset the bangle
}

Bangle.on('kill',()=>{
  Bangle.setCompassPower(0,'kitchen');
  Bangle.setGPSPower(0,'kitchen');
});

Bangle.on('lcdPower',function(on) {
  if (on) {
    startdraw();
  } else {
    stopdraw();
  }
});

/*****************************************************************************

Start of GPS object code so we can share it between faces

******************************************************************************/


function log_debug(o) {
  //console.log(o);
}

function radians(a) {
  return a*Math.PI/180;
}

function degrees(a) {
  var d = a*180/Math.PI;
  return (d+360)%360;
}

function GPS() {
  this.wp;
  this.wp_index = 0;
  this.wp_current = undefined;
  this.GPS_OFF = 0;
  this.GPS_TIME = 1;
  this.GPS_SATS = 2;
  this.GPS_RUNNING = 3;
  this.gpsState = this.GPS_OFF;
  this.gpsPowerState = false;
  this.last_fix = {
    fix: 0,
    alt: 0,
    lat: 0,
    lon: 0,
    speed: 0,
    time: 0,
    satellites: 0
  };
  this.listenerCount = 0;
  this.loadFirstWaypoint();
}

GPS.prototype.log_debug = function(o) {
  //console.log(o);
};

GPS.prototype.getState = function() {
  return this.gpsState;
}

GPS.prototype.getLastFix = function() {
  return this.last_fix;
}

GPS.prototype.determineGPSState = function() {
  this.log_debug("determineGPSState");
  gpsPowerState = Bangle.isGPSOn();

  //this.log_debug("last_fix.fix " + this.last_fix.fix);
  //this.log_debug("gpsPowerState " + this.gpsPowerState);
  //this.log_debug("last_fix.satellites " + this.last_fix.satellites);

  if (!gpsPowerState) {
    this.gpsState = this.GPS_OFF;
    this.resetLastFix();
  } else if (this.last_fix.fix && this.gpsPowerState && this.last_fix.satellites > 0) {
    this.gpsState = this.GPS_RUNNING;
  } else {
    this.gpsState = this.GPS_SATS;
  }

  this.log_debug("gpsState=" + this.gpsState);

  if (this.gpsState !== this.GPS_OFF) {
    if (this.listenerCount === 0) {
      Bangle.on('GPS', processFix);
      this.listenerCount++;
      this.log_debug("listener added " + this.listenerCount);
    }
  } else {
    if (this.listenerCount > 0) {
      Bangle.removeListener("GPS", processFix);
      this.listenerCount--;
      this.log_debug("listener removed " + this.listenerCount);
    }
  }
};

GPS.prototype.getGPSTime = function() {
  var time;

  if (this.last_fix !== undefined && this.last_fix.time !== undefined && this.last_fix.time.toUTCString !== undefined &&
      (this.gpsState == this.GPS_SATS || this.gpsState == this.GPS_RUNNING)) {
    time = this.last_fix.time.toUTCString().split(" ");
    return time[4];
  } else {
    var d = new Date();
    var da = d.toString().split(" ");
    time = da[4].substr(0,5);
    return time;
  }
};

GPS.prototype.toggleGPSPower = function() {
  this.log_debug("toggleGPSPower()");
  this.gpsPowerState = Bangle.isGPSOn();
  this.gpsPowerState = !this.gpsPowerState;
  Bangle.setGPSPower((this.gpsPowerState ? 1 : 0), 'kitchen');

  this.resetLastFix();
  this.determineGPSState();

  // poke the gps widget indicator to change
  if (WIDGETS.gps !== undefined) {
    WIDGETS.gps.draw();
  }
};

GPS.prototype.resetLastFix = function() {
  this.last_fix = {
    fix: 0,
    alt: 0,
    lat: 0,
    lon: 0,
    speed: 0,
    time: 0,
    satellites: 0
  };
};

function processFix(fix) {
  //log_debug("processFix()");
  gpsObj.processFix(fix);
}

GPS.prototype.processFix = function(fix) {
  //this.log_debug("GPS:processFix()");
  //this.log_debug(fix);
  this.last_fix.time = fix.time;

  if (this.gpsState == this.GPS_TIME) {
    this.gpsState = this.GPS_SATS;
  }

  if (fix.fix) {
    //this.log_debug("Got fix - setting state to GPS_RUNNING");
    this.gpsState = this.GPS_RUNNING;
    if (!this.last_fix.fix && !(require("Storage").readJSON("setting.json", 1) || {}).quiet) {
      Bangle.buzz(); // buzz on first position
      debug_log("BUZZ - gps fix");
    }
    this.last_fix = fix;
  }
};

GPS.prototype.formatTime = function(now) {
  var fd = now.toUTCString().split(" ");
  return fd[4];
};

GPS.prototype.timeSince = function(t) {
  var hms = t.split(":");
  var now = new Date();

  var sn = 3600*(now.getHours()) + 60*(now.getMinutes()) + 1*(now.getSeconds());
  var st = 3600*(hms[0]) + 60*(hms[1]) + 1*(hms[2]);

  return (sn - st);
};

GPS.prototype.getOsRef = function() {
  let os = OsGridRef.latLongToOsGrid(this.last_fix);
  let ref = to_map_ref(6, os.easting, os.northing);
  return ref;
};

GPS.prototype.calcBearing = function(a,b) {
  var delta = radians(b.lon-a.lon);
  var alat = radians(a.lat);
  var blat = radians(b.lat);
  var y = Math.sin(delta) * Math.cos(blat);
  var x = Math.cos(alat)*Math.sin(blat) -
      Math.sin(alat)*Math.cos(blat)*Math.cos(delta);
  return Math.round(degrees(Math.atan2(y, x)));
}

GPS.prototype.calcDistance = function(a,b) {
  var x = radians(a.lon-b.lon) * Math.cos(radians((a.lat+b.lat)/2));
  var y = radians(b.lat-a.lat);
  return Math.round(Math.sqrt(x*x + y*y) * 6371000);
}

GPS.prototype.getWPdistance = function() {
  //log_debug(this.last_fix);
  //log_debug(this.wp_current);

  if (this.wp_current.name === "E-WPT" || this.wp_current.name === "NONE" || this.wp_current.lat === undefined || this.wp_current.lat === 0)
    return 0;
  else
    return this.calcDistance(this.last_fix, this.wp_current);
}

GPS.prototype.getWPbearing = function() {
  //log_debug(this.last_fix);
  //log_debug(this.wp_current);

  if (this.wp_current.name === "E-WPT" || this.wp_current.name === "NONE" || this.wp_current.lat === undefined || this.wp_current.lat === 0)
    return 0;
  else
    return this.calcBearing(this.last_fix, this.wp_current);
}

GPS.prototype.loadFirstWaypoint = function() {
  var waypoints = require("waypoints").load();
  this.wp_index = 0;
  this.wp_current = waypoints[this.wp_index];
  log_debug(this.wp_current);
  return this.wp_current;
}

GPS.prototype.getCurrentWaypoint = function() {
  return this.wp_current;
}

GPS.prototype.waypointHasLocation = function() {
  if (this.wp_current.name === "E-WPT" || this.wp_current.name === "NONE" || this.wp_current.lat === undefined || this.wp_current.lat === 0)
    return false;
  else
    return true;
}

GPS.prototype.markWaypoint = function() {

  if(this.wp_current.name === "E-WPT" || this.wp_current.name === "NONE")
    return;

  log_debug("GPS::markWaypoint()");

  var waypoints = require("waypoints").load();
  this.wp_current = waypoints[this.wp_index];

  if (this.waypointHasLocation()) {
     waypoints[this.wp_index] = {name:this.wp_current.name, lat:0, lon:0};
  } else {
     waypoints[this.wp_index] = {name:this.wp_current.name, lat:this.last_fix.lat, lon:this.last_fix.lon};
  }

  this.wp_current = waypoints[this.wp_index];
  require("waypoints").save(waypoints);
  log_debug("GPS::markWaypoint() written");
}

GPS.prototype.nextWaypoint = function(inc) {
  var waypoints = require("waypoints").load();
  this.wp_index+=inc;
  if (this.wp_index>=waypoints.length) this.wp_index=0;
  if (this.wp_index<0) this.wp_index = waypoints.length-1;
  this.wp_current = waypoints[this.wp_index];
  log_debug(this.wp_current);
  return this.wp_current;
}

GPS.prototype.toggleGpsLogging = function() {
  var settings = require("Storage").readJSON("gpsrec.json",1)||{};
  if (settings == {}) return false;

  settings.recording = !settings.recording;
  require("Storage").write("gpsrec.json", settings);

  if (WIDGETS["gpsrec"])
    WIDGETS["gpsrec"].reload();

  return true;
}

GPS.prototype.loggingStatus = function() {
  var settings = require("Storage").readJSON("gpsrec.json",1)||{};
  if (settings == {}) return "E-LOG";
  if (settings.recording) return "ON";
  return "OFF";
}

var gpsObj = new GPS();


/*****************************************************************************

Start of OS lat lon to grid ref code

******************************************************************************/

Number.prototype.toRad = function() { return this*Math.PI/180; };
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
/*  Ordnance Survey Grid Reference functions  (c) Chris Veness 2005-2014                          */
/*   - www.movable-type.co.uk/scripts/gridref.js                                                  */
/*   - www.movable-type.co.uk/scripts/latlon-gridref.html                                         */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
function OsGridRef(easting, northing) {
  this.easting = 0|easting;
  this.northing = 0|northing;
}

OsGridRef.latLongToOsGrid = function(point) {
  var lat = point.lat.toRad();
  var lon = point.lon.toRad();

  var a = 6377563.396, b = 6356256.909;          // Airy 1830 major & minor semi-axes
  var F0 = 0.9996012717;                         // NatGrid scale factor on central meridian
  var lat0 = (49).toRad(), lon0 = (-2).toRad();  // NatGrid true origin is 49Ã¯Â¿Â½N,2Ã¯Â¿Â½W
  var N0 = -100000, E0 = 400000;                 // northing & easting of true origin, metres
  var e2 = 1 - (b*b)/(a*a);                      // eccentricity squared
  var n = (a-b)/(a+b), n2 = n*n, n3 = n*n*n;

  var cosLat = Math.cos(lat), sinLat = Math.sin(lat);
  var nu = a*F0/Math.sqrt(1-e2*sinLat*sinLat);              // transverse radius of curvature
  var rho = a*F0*(1-e2)/Math.pow(1-e2*sinLat*sinLat, 1.5);  // meridional radius of curvature
  var eta2 = nu/rho-1;

  var Ma = (1 + n + (5/4)*n2 + (5/4)*n3) * (lat-lat0);
  var Mb = (3*n + 3*n*n + (21/8)*n3) * Math.sin(lat-lat0) * Math.cos(lat+lat0);
  var Mc = ((15/8)*n2 + (15/8)*n3) * Math.sin(2*(lat-lat0)) * Math.cos(2*(lat+lat0));
  var Md = (35/24)*n3 * Math.sin(3*(lat-lat0)) * Math.cos(3*(lat+lat0));
  var M = b * F0 * (Ma - Mb + Mc - Md);              // meridional arc

  var cos3lat = cosLat*cosLat*cosLat;
  var cos5lat = cos3lat*cosLat*cosLat;
  var tan2lat = Math.tan(lat)*Math.tan(lat);
  var tan4lat = tan2lat*tan2lat;

  var I = M + N0;
  var II = (nu/2)*sinLat*cosLat;
  var III = (nu/24)*sinLat*cos3lat*(5-tan2lat+9*eta2);
  var IIIA = (nu/720)*sinLat*cos5lat*(61-58*tan2lat+tan4lat);
  var IV = nu*cosLat;
  var V = (nu/6)*cos3lat*(nu/rho-tan2lat);
  var VI = (nu/120) * cos5lat * (5 - 18*tan2lat + tan4lat + 14*eta2 - 58*tan2lat*eta2);

  var dLon = lon-lon0;
  var dLon2 = dLon*dLon, dLon3 = dLon2*dLon, dLon4 = dLon3*dLon, dLon5 = dLon4*dLon, dLon6 = dLon5*dLon;

  var N = I + II*dLon2 + III*dLon4 + IIIA*dLon6;
  var E = E0 + IV*dLon + V*dLon3 + VI*dLon5;

  return new OsGridRef(E, N);
};

/*
 * converts northing, easting to standard OS grid reference.
 *
 * [digits=10] - precision (10 digits = metres)
 *   to_map_ref(8, 651409, 313177); => 'TG 5140 1317'
 *   to_map_ref(0, 651409, 313177); => '651409,313177'
 *
 */
function to_map_ref(digits, easting, northing) {
  if (![ 0,2,4,6,8,10,12,14,16 ].includes(Number(digits))) throw new RangeError(`invalid precision '${digits}'`); // eslint-disable-line comma-spacing

  let e = easting;
  let n = northing;

  // use digits = 0 to return numeric format (in metres) - note northing may be >= 1e7
  if (digits == 0) {
    const format = { useGrouping: false,  minimumIntegerDigits: 6, maximumFractionDigits: 3 };
    const ePad = e.toLocaleString('en', format);
    const nPad = n.toLocaleString('en', format);
    return `${ePad},${nPad}`;
  }

  // get the 100km-grid indices
  const e100km = Math.floor(e / 100000), n100km = Math.floor(n / 100000);

  // translate those into numeric equivalents of the grid letters
  let l1 = (19 - n100km) - (19 - n100km) % 5 + Math.floor((e100km + 10) / 5);
  let l2 = (19 - n100km) * 5 % 25 + e100km % 5;

  // compensate for skipped 'I' and build grid letter-pairs
  if (l1 > 7) l1++;
  if (l2 > 7) l2++;
  const letterPair = String.fromCharCode(l1 + 'A'.charCodeAt(0), l2 + 'A'.charCodeAt(0));

  // strip 100km-grid indices from easting & northing, and reduce precision
  e = Math.floor((e % 100000) / Math.pow(10, 5 - digits / 2));
  n = Math.floor((n % 100000) / Math.pow(10, 5 - digits / 2));

  // pad eastings & northings with leading zeros
  e = e.toString().padStart(digits/2, '0');
  n = n.toString().padStart(digits/2, '0');

  return `${letterPair} ${e} ${n}`;
}


/*****************************************************************************

Stopwatch Class Code

******************************************************************************/


function STOPWATCH() {
  this.tTotal = Date.now();
  this.tStart = Date.now();
  this.tCurrent = Date.now();
  this.running = false;
  this.timeY = 45;
  this.TtimeY = 75;
  this.lapTimes = [];
  this.displayInterval;
  this.redrawButtons = true;
  this.redrawLaps = true;
  this.redrawTime = true;
}

STOPWATCH.prototype.log_debug = function(o) {
  //console.log(o);
}

STOPWATCH.prototype.timeToText = function(t) {
  let hrs = Math.floor(t/3600000);
  let mins = Math.floor(t/60000)%60;
  let secs = Math.floor(t/1000)%60;
  let text;

  if (hrs === 0)
    text = ("0"+mins).substr(-2) + ":" + ("0"+secs).substr(-2);
  else
    text = (""+hrs) + ":" + ("0"+mins).substr(-2) + ":" + ("0"+secs).substr(-2);

  this.log_debug(text);
  return text;
}

STOPWATCH.prototype.getLapTimesArray = function() {
  this.lapTimes.push(tCurrent-tTotal);
  return this.lapTimes.map(timeToText).reverse();
}

STOPWATCH.prototype.stopStart = function() {
  this.log_debug("stopStart()");
  this.running = !this.running;

  if (this.running)
    this.tStart = Date.now() + this.tStart - this.tCurrent;

  this.tTotal = Date.now() + this.tTotal - this.tCurrent;
  this.tCurrent = Date.now();
  this.redrawButtons = true;
  this.redrawLaps = true;
  this.redrawTime = true;
  this.draw();
}

STOPWATCH.prototype.lap = function() {
  this.log_debug("lap()");
  if (this.running) {
    this.tCurrent = Date.now();
    this.lapTimes.unshift(this.tCurrent - this.tStart);
    log_debug(this.tCurrent - this.tStart);
  }

  this.tStart = this.tCurrent;
  this.redrawButtons = true;
  this.redrawLaps = true;
  this.draw();
}

STOPWATCH.prototype.reset = function() {
  this.log_debug("reset()");
  if (this.running === false) {
    this.tStart = this.tCurrent = this.tTotal = Date.now();
    this.lapTimes = [];
  }
  g.clear();
  this.draw();
}

// lap or reset
STOPWATCH.prototype.lapOrReset = function() {
  this.redrawButtons = true;
  this.redrawLaptimes = true;
  this.redrawTime = true;

  this.log_debug("lapReset()");
  if (this.running)
    this.lap()
  else
    this.reset();
}

STOPWATCH.prototype.draw = function() {
  if (this.running) this.tCurrent = Date.now();
  this.log_debug("draw()" + getTime());

  g.setColor(1,1,1);
  if (this.redrawButtons) this.drawButtons();
  if (this.running || this.redrawTime) this.drawTime();
  if (this.redrawLaps) this.drawLaptimes();
}

STOPWATCH.prototype.drawButtons = function() {
  this.log_debug("drawButtons()");

  g.clearRect(0,23,g.getWidth()-1,g.getHeight()-24);
  g.setColor(1,1,1);
  g.setFont("Vector", 20);
  g.setFontAlign(0,0,3);
  g.drawString(this.running? "STOP" : "GO",    230, 50); // BTN1
  g.drawString(this.running? "LAP"  : "RESET", 230, 120); // BTN2
  this.redrawButtons = false;
}

STOPWATCH.prototype.drawLaptimes = function() {
  g.setFont("Vector",24);
  g.setFontAlign(-1,-1);
  g.clearRect(4, 205, 239, 229); // clear the last line of the lap times

  let laps = 0;
  for (let i in this.lapTimes) {
    g.drawString(this.lapTimes.length-i + ": " + this.timeToText(this.lapTimes[i]), 4, this.timeY + 40 + i*24);
    if (++laps > 5) break;
  }
  this.redrawLaps = false;
}

STOPWATCH.prototype.drawTime = function() {
  this.log_debug("drawTime()");
  let tLap = this.tCurrent - this.tStart;
  let tTotal = this.tCurrent - this.tTotal;
  let txtLap = this.timeToText(tLap);
  let txtTotal = this.timeToText(tTotal);
  let xTotal = 100;
  let xLap = 125;

  // total time
  g.setFont("Vector",38);
  g.setFontAlign(0,0);
  g.clearRect(0, this.timeY-21, 200, this.timeY+21);
  g.setColor(0xFFC0);
  g.drawString(txtTotal, xTotal, this.timeY);

  // current lap time
  g.setFont("Vector", 20);
  g.clearRect(0, this.TtimeY-7, 200, this.TtimeY+7);
  g.setColor(1,1,1);
  g.drawString(txtLap, xLap, this.TtimeY);

  this.redrawTime = false;
}

STOPWATCH.prototype.startTimer = function() {
  this.log_debug("startTimer()");
  this.redrawButtons = true;
  this.redrawLaps = true;
  this.redrawTime = true;
  this.draw();
  this.displayInterval = setInterval(stopwatchDraw, 1000);
}

STOPWATCH.prototype.stopTimer = function() {
  this.log_debug("stopTimer()");
  if (this.displayInterval) {
    clearInterval(this.displayInterval);
    this.displayInterval = undefined;
  }
}

let swObj = new STOPWATCH();

function stopwatchDraw() {
  swObj.draw();
}


/*****************************************************************************

Heart Rate Monitor

******************************************************************************/

function HRM() {
  this.bpm = 0;
  this.confidence = 0;
}

HRM.prototype.log_debug = function(o) {
  //console.log(o);
}

HRM.prototype.toggleHRMPower = function() {
  this.log_debug("HRM.toggleHRMPower()");
  if (!Bangle.isHRMOn) return; // old firmware

  if (!Bangle.isHRMOn()) {
    this.log_debug("HRM.toggleHRMPower(powerOn)");
    Bangle.removeListener('HRM', onHRM);
    Bangle.setHRMPower(1);
    Bangle.on('HRM', onHRM);
  } else {
    this.log_debug("HRM.toggleHRMPower(powerOff)");
    Bangle.removeListener('HRM', onHRM);
    Bangle.setHRMPower(0);
  }

  // poke the hrt widget indicator to change
  if (WIDGETS.widhrt !== undefined) {
    WIDGETS.widhrt.draw();
  }
}

HRM.prototype.getBpm = function() {
  return this.bpm;
}

HRM.prototype.getConfidence = function() {
  return this.confidence;
}

HRM.prototype.onHRM = function(hrm) {
  this.bpm = hrm.bpm;
  this.confidence = hrm.confidence;
  this.log_debug("onHRM:(bpm)" + this.bpm);
  this.log_debug("onHRM:(conf) " + this.confidence);
}

let hrmObj = new HRM();

function onHRM(hrm) {
  hrmObj.onHRM(hrm);
}


/*****************************************************************************

Trip Counter

******************************************************************************/

function TRIP() {
  this.showTrip = false;
  this.tripStart = 0;
}

TRIP.prototype.resetTrip = function(steps) {
  this.tripStart = (0 + steps);
  log_debug("resetTrip starting=" + this.tripStart);
}

TRIP.prototype.getTrip = function(steps) {
  let tripSteps = (0 + steps) - this.tripStart;
  log_debug("getTrip steps=" + steps);
  log_debug("getTrip tripStart=" + this.tripStart);
  log_debug("getTrip=" + tripSteps);
  return tripSteps;
}

TRIP.prototype.getTripState = function() {
  return this.showTrip;
}

TRIP.prototype.setTripState = function(t) {
  this.showTrip = t;
}

let tripObject = new TRIP();

/*****************************************************************************

Debug Object

******************************************************************************/

function DEBUG() {
  this.logfile = require("Storage").open("debug.log","a");
}

DEBUG.prototype.log = function(msg) {
  let timestamp = new Date().toString().split(" ")[4];
  let line = timestamp + ", " + msg + "\n";
  this.logfile.write(line);
}

debugObj = new DEBUG();

function debug_log(m) {
  //debugObj.log(m);
}

/*****************************************************************************

Start App

******************************************************************************/

g.clear();
Bangle.loadWidgets();
face.init(gpsObj,swObj, hrmObj, tripObject);
startdraw();
setButtons();
