(function() {
  const alarm = require('sched');
  const iconAlarmOn = atob("GBiBAAAAAAAAAAYAYA4AcBx+ODn/nAP/wAf/4A/n8A/n8B/n+B/n+B/n+B/n+B/h+B/4+A/+8A//8Af/4AP/wAH/gAB+AAAAAAAAAA==");
  const iconAlarmOff = atob("GBiBAAAAAAAAAAYAYA4AcBx+ODn/nAP/wAf/4A/n8A/n8B/n+B/n+B/nAB/mAB/geB/5/g/5tg/zAwfzhwPzhwHzAwB5tgAB/gAAeA==");
  const iconTimerOn = atob("GBiBAAAAAAAAAAAAAAf/4Af/4AGBgAGBgAGBgAD/AAD/AAB+AAA8AAA8AAB+AADnAADDAAGBgAGBgAGBgAf/4Af/4AAAAAAAAAAAAA==");
  const iconTimerOff = atob("GBiBAAAAAAAAAAAAAAf/4Af/4AGBgAGBgAGBgAD/AAD/AAB+AAA8AAA8AAB+AADkeADB/gGBtgGDAwGDhwfzhwfzAwABtgAB/gAAeA==");

  //from 0 to max, the higher the closer to fire (as in a progress bar)
  function getAlarmValue(a){
    let min = Math.round(alarm.getTimeToAlarm(a)/(60*1000));
    if(!min) return 0; //not active or more than a day
    return getAlarmMax(a)-min;
  }

  function getAlarmMax(a) {
    if(a.timer)
      return Math.round(a.timer/(60*1000));
    //minutes cannot be more than a full day
    return 1440;
  }

  function getAlarmIcon(a) {
    if(a.on) {
      if(a.timer) return iconTimerOn;
      return iconAlarmOn;
    } else {
      if(a.timer) return iconTimerOff;
      return iconAlarmOff;
    }
  }

  function getAlarmText(a){
    if(a.timer) {
      if(!a.on) return /*LANG*/"off";
      let time = Math.round(alarm.getTimeToAlarm(a)/(60*1000));
      if(time > 60)
        time = Math.round(time / 60) + "h";
      else
        time += "m";
      return time;
    }
    return require("time_utils").formatTime(a.t);
  }

  //workaround for sorting undefined values
  function getAlarmOrder(a) {
    let val = alarm.getTimeToAlarm(a);
    if(typeof val == "undefined") return 86400*1000;
    return val;
  }

  /*
   * Returns the array [interval, switchTimeout]
   * `interval` is the refresh rate (hourly or per minute)
   * `switchTimeout` is the time before the refresh rate should change (or expiration)
   */
  function getRefreshIntervals(a) {
    const minute = 60 * 1000;
    const halfhour = 30 * minute;
    const hour = 2 * halfhour;
    let msecs = alarm.getTimeToAlarm(a);
    if(typeof msecs == "undefined" || msecs == 0)
      return [];
    if(msecs > hour) { //refresh every half an hour
      let remain = (msecs+minute) % halfhour;
      if(remain < 27 * minute && remain != 0) //first align period (some tolerance)
        return [ halfhour, remain ];
      return [ halfhour, msecs - hour ];
    } else { //refresh every minute
      //alarms just need the progress bar refreshed, no need every minute
      if(!a.timer) return [];
      return [ minute, msecs ];
    }
  }

  function _doInterval(interval) {
    return setTimeout(()=>{
      this.emit("redraw");
      this.interval = setInterval(()=>{
        this.emit("redraw");
      }, interval);
    }, interval);
  }
  function _doSwitchTimeout(a, switchTimeout) {
    return setTimeout(()=>{
      this.emit("redraw");
      clearInterval(this.interval);
      this.interval = undefined;
      var tmp = getRefreshIntervals(a);
      var interval = tmp[0];
      var switchTimeout = tmp[1];
      if(!interval) return;
      this.interval = _doInterval.call(this, interval);
      this.switchTimeout = _doSwitchTimeout.call(this, a, switchTimeout);
    }, switchTimeout);
  }

  var img = iconAlarmOn;
  //get only alarms not created by other apps
  var alarmItems = {
    name: /*LANG*/"Alarms",
    img: img,
    dynamic: true,
    items: alarm.getAlarms().filter(a=>!a.appid)
    //.sort((a,b)=>alarm.getTimeToAlarm(a)-alarm.getTimeToAlarm(b))
    .sort((a,b)=>getAlarmOrder(a)-getAlarmOrder(b))
      .map((a, i)=>({
        name: null,
        hasRange: true,
        get: () => ({ text: getAlarmText(a), img: getAlarmIcon(a),
          v: getAlarmValue(a), min:0, max:getAlarmMax(a)}),
        show: function() {
          var tmp = getRefreshIntervals(a);
          var interval = tmp[0];
          var switchTimeout = tmp[1];
          if(!interval) return;
          this.interval = _doInterval.call(this, interval);
          this.switchTimeout = _doSwitchTimeout.call(this, a, switchTimeout);
        },
        hide: function() {
          if (this.interval) clearInterval(this.interval);
          if (this.switchTimeout) clearTimeout(this.switchTimeout);
          this.interval = undefined;
          this.switchTimeout = undefined;
        },
        run: function() { }
      })),
  };

  return alarmItems;
})
