%D \module
%D   [      file=s-youless,
%D        version=2013.11.12,
%D          title=\CONTEXT\ Style File,
%D       subtitle=Youless Graphics,
%D         author=Hans Hagen,
%D           date=\currentdate,
%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.

%D This is experimental code. When I have collected enough data I will make the
%D graphics nicer and provide some more.
%D
%D The Jouless can serve web pages but there is not much detail in them. They also are
%D somewhat bad \HTML, like unquoted attributes and so. We don't need this anyway as we
%D can also fetch data directly. The data is collected using a dedicated helper script
%D (of course we could just call it as module too). The data is fetched from the Jouless
%D device using queries (currently we use json, but a more direct parsing of data might
%D be more efficient). The data is converted into a proper \LUA\ table and saved (merged).

% in cronjob on one of the servers:
%
% mtxrun --script youless --collect --host=192.168.2.50 --nobackup --electricity youless-electricity.lua

\startluacode

    require("util-you")

    local round = math.round

    moduledata.youless = { }

    local defaults = {
        electricity = {
            unit    = "watt",
            maxunit = "maxwatt",
        },
        watt        = {
            unit    = "watt",
            maxunit = "maxwatt",
        },
        pulse       = {
            unit    = "watt",
            maxunit = "maxwatt",
        },
        gas         = {
            unit    = "liters",
            maxunit = "maxliters",
        },
    }

    local function process(specification,thevariant)

        local data, message = utilities.youless.analyze(specification.filename or "youless-electricity.lua")

        if not data then
            context(message)
            return
        end

        local variant = data.variant
        local unit    = specification.unit
        local maxunit = specification.maxunit

        if thevariant then
            if variant ~= thevariant then
                context("invalid variant")
                return
            end
        elseif variant then
            local d = defaults[variant]
            if d then
                unit    = d.unit
                maxunit = d.maxunit
            else
                context("unknown variant")
                return
            end
        else
            context("invalid variant")
            return
        end

        local year    = tonumber(specification.year) or os.today().year
        local month   = tonumber(specification.month)
        local years   = data.years
        local max     = specification[maxunit]

        if not max then
            if unit == "watt" then
                max = 10000
            elseif unit == "liters" then
                max = 1000
            else
                max = 5000 -- can't happen
            end
        end

        local firstmonth = month or 1
        local lastmonth  = month or 12

        local max   = max
        local delta = round(max/10)
        local scale = round(delta/20)
        local mark  = 3

        for y=year,year do
            local year = years[y]
            if year then
                local grand = 0
                for m=firstmonth,lastmonth do
                    local month = year.months[m]
                    if month then
                        context.startMPpage { offset = "10pt" }
                        context("linecap := butt; pickup pencircle scaled .5")

                        for i=0,(math.div(max,delta)+1)*delta,delta/10 do
                            context("draw (%s,%s) -- (%s,%s) withcolor .6white ;",0,i/scale,31 * 24,i/scale)
                        end

                        context("draw (0,%s) -- (31 * 24,%s) dashed dashpattern(on 6 off 6) withcolor darkgreen withpen pencircle scaled 1 ;",year [unit]/scale,year [unit]/scale)
                        context("draw (0,%s) -- (31 * 24,%s) dashed dashpattern(off 6 on 6) withcolor darkred   withpen pencircle scaled 1 ;",month[unit]/scale,month[unit]/scale)

                        local days  = month.days
                        local total = 0
                        if days then
                            local nd = os.nofdays(y,m)
                            for d=1,nd do
                                local day     = days[d]
                                local xoffset = (d-1) * 24
                                local wd      = os.weekday(d,m,y)
                                local weekend = wd == 1 or wd == 7
                                if not weekend then
                                    -- okay
                                elseif mark == 1 then
                                    context("draw (%s,%s) -- (%s,%s) ; ",xoffset,   -17.5,xoffset,   -32.5)
                                    context("draw (%s,%s) -- (%s,%s) ; ",xoffset+24,-17.5,xoffset+24,-32.5)
                                elseif mark == 2 then
                                    context("draw (%s,%s) -- (%s,%s) ;",xoffset,    -17.5,xoffset+24,-17.5)
                                    context("draw (%s,%s) -- (%s,%s) ;",xoffset,    -32.5,xoffset+24,-32.5)
                                elseif mark == 3 then
                                    context("draw unitsquare xysized (%s,%s) shifted (%s,%s) ;",24,15,xoffset,-32.5)
                                end
                                context([[draw textext("\strut%s") shifted (%s,%s) ;]],d,xoffset + 12,-25)
                                if day then
                                    for h=0,23 do
                                        local hours = day.hours
                                        if hours then
                                            local hour = hours[h]
                                            if hour then
                                                local dx = xoffset + h
                                                local dy = hour[unit]/scale
                                                local dm = hour[maxunit]/scale
                                                context("draw (%s,%s) -- (%s,%s) withcolor %s ;",dx, 0,dx,dy,weekend and "darkmagenta" or "darkblue")
                                                context("draw (%s,%s) -- (%s,%s) withcolor %s ;",dx,dy,dx,dm,"darkgray")
                                            end
                                        end
                                    end
                                    local use = day.total
                                    if use then
                                        context([[draw textext("\strut\small\small\small%0.1f") shifted (%s,%s) ;]],use/1000,xoffset + 12,-7.5)
                                        total = total + use
                                    end
                                end
                            end
                            for d=0,30 do
                                local xoffset = d * 24
                                context("draw (%s,%s) -- (%s,%s) withcolor darkgray ;",xoffset+ 0,0,xoffset+ 0,-10)
                                context("draw (%s,%s) -- (%s,%s) withcolor darkgray ;",xoffset+ 6,0,xoffset+ 6,-2.5)
                                context("draw (%s,%s) -- (%s,%s) withcolor darkgray ;",xoffset+12,0,xoffset+12,-5)
                                context("draw (%s,%s) -- (%s,%s) withcolor darkgray ;",xoffset+18,0,xoffset+18,-2.5)
                            end
                            local xoffset = 31 * 24
                            context("draw (%s,%s) -- (%s,%s) withcolor darkgray ;",xoffset,0,xoffset,-10)
                        end

                        grand = grand + total

                        local max = (math.div(max,delta))

                        for i=0,max*delta,delta do
                            if i > 0 then
                                context([[draw textext.lft("\hbox to 3.5em{\hss\strut%r}") shifted (%s,%s) ; ]],i,-10,i/scale)
                            end
                            context("draw (%s,%s) -- (%s,%s) withcolor .2white ;",0,i/scale,31 * 24,i/scale)
                        end

                        context([[draw textext    ("\strut\Word{%s}\enspace\emdash\enspace\month{%s}\enspace%s") shifted (%s,%s) ; ]],variant, m, y, 31 * 24 / 2, -50)
                        context([[draw textext.lft("\hbox to 3.5em{\hss\strut%s}") shifted (%s,%s) ; ]],unit,-10,-25)
                        context([[draw textext.lft("\hbox to 3.5em{\hss\strut\small\small\small%0.1f %s}") shifted (%s,%s) ;]],total/1000,unit == "watt" and "kWh" or [[m\high{3}]],-10, -7.5)
                        context([[draw textext.lft("\hbox to 3.5em{\hss\strut\small\small\small\Sigma\nbsp%0.1f %s}") shifted (%s,%s) ;]],grand/1000,unit == "watt" and "kWh" or [[m\high{3}]],-10,-50.0)

                        context.stopMPpage()
                    else
                        -- maybe placeholder
                    end
                end
            end
        end
    end

    function moduledata.youless.kwh(specification)
        -- todo
    end

    function moduledata.youless.electricity(specification)
        specification.unit    = "watt"
        specification.maxunit = "maxwatt"
        process(specification,"electricity")
    end

    moduledata.youless.watt = moduledata.youless.electricity

    function moduledata.youless.gas(specification)
        specification.unit    = "liters"
        specification.maxunit = "maxliters"
        process(specification,"gas")
    end

    function moduledata.youless.pulse(specification)
        specification.unit    = "watt"
        specification.maxunit = "maxwatt"
        process(specification,"pulse")
    end

    function moduledata.youless.graphics(specification)
        process(specification)
    end

\stopluacode

\continueifinputfile{s-youless.mkiv}

\setupbodyfont[dejavu] % smaller sizes also look ok

% printer (oce)  : > 3000 W startup (900 W idle, 2000 W printing)
% coffeemaker    :   1500 W when heating

% baseline day   :   2250 W (servers, airco, workstations, routers, switches, heating, etc)
% baseline night :   1750 W

\starttext

    \startluacode

     -- os.execute([[mtxrun --script youless --collect --electricity "c:/data/system/youless/data/youless-electricity.lua"]])
     -- os.execute([[mtxrun --script youless --collect --electricity --nobackup "c:/data/system/youless/data/youless-electricity.lua"]])
     -- moduledata.youless.electricity { year = 2017, filename = "c:/data/system/youless/data/youless-electricity.lua" }

        moduledata.youless.electricity { year = 2017, filename = "youless-electricity.lua" }

    \stopluacode

\stoptext
