--!name Focus Timer
--!icon clock
--!category Tools
-- Pomodoro-style focus timer: 25 minutes of work, then a 5-minute break.
--
-- Counts against the real clock (os.time) and redraws once a minute, so the
-- e-ink panel isn't refreshed every second while it runs, and the time stays
-- right even if a redraw comes late.

local FOCUS, BREAK = 25 * 60, 5 * 60
local mode = "focus"  -- "focus" or "break"
local left = FOCUS    -- seconds left, kept while paused
local endsAt = nil    -- os.time() the round finishes; nil while paused
local done = false    -- the round ran out; waiting for OK to start the next

local function remaining()
  if endsAt then return math.max(0, endsAt - os.time()) end
  return left
end

-- Asks for the next step when the minute shown changes (or at the end).
local function arm()
  if not endsAt then
    snail.tick(0)
    return
  end
  local r = remaining()
  local toNextMinute = r % 60
  if toNextMinute == 0 then toNextMinute = 60 end
  snail.tick(math.max(1, math.min(r, toNextMinute)) * 1000)
end

local function reset(newMode)
  mode = newMode
  left = mode == "focus" and FOCUS or BREAK
  endsAt = nil
  done = false
end

function start()
  arm()
end

function tick()
  if endsAt and remaining() == 0 then
    endsAt = nil
    left = 0
    done = true
  end
  arm()
end

function key(k)
  if k == "ok" then
    if done then
      reset(mode == "focus" and "break" or "focus")
      endsAt = os.time() + left
    elseif endsAt then
      left = remaining()  -- pause
      endsAt = nil
    else
      endsAt = os.time() + left  -- start or resume
    end
  elseif k == "left" or k == "right" then
    reset(mode == "focus" and "break" or "focus")
  elseif k == "up" or k == "down" then
    -- A minute more or less, between 1 and 90.
    local r = remaining()
    local step = k == "up" and 60 or -60
    local new = math.min(90 * 60, math.max(60, r + step))
    if endsAt then endsAt = endsAt + (new - r) else left = new end
    done = false
  end
  arm()
end

function draw()
  snail.title(mode == "focus" and "Focus" or "Break")
  snail.gap()
  snail.center(true)
  if done then
    snail.text(mode == "focus" and "Done! Time for a break." or "Break's over.")
    snail.small(mode == "focus" and "OK starts the break" or "OK starts the next focus")
  else
    local minutes = math.ceil(remaining() / 60)
    snail.text(string.format("%d min left", minutes))
    snail.small(endsAt and "Running" or "Paused")
  end
  snail.center(false)
  snail.gap()
  snail.rule()
  snail.small("OK start or pause")
  snail.small("LEFT/RIGHT switch focus and break")
  snail.small("UP/DOWN a minute more or less")
  snail.hint("OK start/pause   L/R mode")
end
