--
-- ion/mod_statusbar/ion-statusd/statusd_mail.lua
--
-- Copyright (c) Tuomo Valkonen 2004-2006.
--
-- Ion is free software; you can redistribute it and/or modify it under
-- the terms of the GNU Lesser General Public License as published by
-- the Free Software Foundation; either version 2.1 of the License, or
-- (at your option) any later version.
--

-- The keyword for this monitor
local mon = "mail"

local defaults={
    update_interval=10*1000,
    retry_interval=60*10*1000,
    mbox = os.getenv("MAIL"),
    files = {}
}

local settings=table.join(statusd.get_config(mon), defaults)

local function TR(s, ...)
    return string.format(statusd.gettext(s), ...)
end

local function check_spool()
    if not settings.mbox then
        statusd.warn(TR("MAIL environment variable not set "..
                        "and no spool given."))
    end
end

if not settings.files["spool"] then
    check_spool()
    settings.files["spool"] = settings.mbox
elseif not(settings.files["spool"] == mbox) then
    statusd.warn(TR("%s.mbox does not match %s.files['spool']; using %s.mbox",
		    mon, mon, mon))
    check_spool()
    settings.files["spool"] = settings.mbox
end

local function calcmail(fname)
    local f, err=io.open(fname, 'r')
    local total, read, old=0, 0, 0
    local had_blank=true
    local in_headers=false
    local had_status=false

    if not f then
        statusd.warn(err)
        return
    end

    for l in f:lines() do
        if had_blank and string.find(l, '^From ') then
            total=total+1
            had_status=false
            in_headers=true
            had_blank=false
        else
            had_blank=false
            if l=="" then
                if in_headers then
                    in_headers=false
                end
                had_blank=true
            elseif in_headers and not had_status then
                local st, en, stat=string.find(l, '^Status:(.*)')
                if stat then
                    had_status=true
                    if string.find(l, 'R') then
                        read=read+1
                    end
                    if string.find(l, 'O') then
                        old=old+1
                    end
                end
            end
        end
    end

    f:close()

    return total, total-read, total-old
end


local mail_timer
local mail_timestamps = {}
function init_timestamps ()
    for key, val in pairs(settings.files) do
        mail_timestamps[key]=-2.0
    end
end
init_timestamps()

local function update_mail()
    local failed
    for key, mbox in pairs(settings.files) do
        if not mbox then
            error(TR(key.." not set"))
        end

        local old_tm=mail_timestamps[key]
        mail_timestamps[key]=statusd.last_modified(mbox)

        if mail_timestamps[key]>old_tm then
	    local mail_total, mail_unread, mail_new=calcmail(mbox)
	    if failed == nil then
	        failed = not mail_total
	    else
	        failed = failed and (not mail_total)
	    end

	    if key == "spool" then
	        meter=mon
	    else
	        meter=mon.."_"..key
	    end
	    if mail_total then
	        statusd.inform(meter.."_new", tostring(mail_new))
	        statusd.inform(meter.."_unread", tostring(mail_unread))
	        statusd.inform(meter.."_total", tostring(mail_total))

	        if mail_new>0 then
		    statusd.inform(meter.."_new_hint", "important")
	        else
		    statusd.inform(meter.."_new_hint", "normal")
	        end

	        if mail_unread>0 then
		    statusd.inform(meter.."_unread_hint", "important")
	        else
		    statusd.inform(meter.."_unread_hint", "normal")
	        end
	    end
	end
    end

    if failed then
        statusd.warn(TR("Disabling mail monitor for %d seconds.",
			settings.retry_interval/1000))
	init_timestamps()
	mail_timer:set(settings.retry_interval, update_mail)
	return
    end

    mail_timer:set(settings.update_interval, update_mail)
end

mail_timer=statusd.create_timer()
update_mail()

