if not modules then modules = { } end modules ['spac-ali'] = {
    version   = 1.001,
    optimize  = true,
    comment   = "companion to spac-ali.mkiv",
    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
    copyright = "PRAGMA ADE / ConTeXt Development Team",
    license   = "see context related readme files"
}

local div = math.div
local format = string.format

local tasks            = nodes.tasks
local enableaction     = tasks.enableaction

local nuts             = nodes.nuts

local setlist          = nuts.setlist
local setlink          = nuts.setlink
local getdirection     = nuts.getdirection
local takeattr         = nuts.takeattr
local getwidth         = nuts.getwidth
local findtail         = nuts.tail

local righttoleft_code <const> = tex.directioncodes.righttoleft

local linelist_code    <const> = nodes.listcodes.line

local hpack_nodes      = nuts.hpack
local nextlist         = nuts.traversers.list

local new_stretch      = nuts.pool.stretch

local a_realign        <const> = attributes.private("realign")
local c_realpageno     <const> = tex.iscount("realpageno")

local texsetattribute  = tex.setattribute
local texgetcount      = tex.getcount

local isleftpage       = layouts.status.isleftpage

typesetters            = typesetters or { }
local alignments       = { }
typesetters.alignments = alignments

local report_realign   = logs.reporter("typesetters","realign")
local trace_realign    = trackers.register("typesetters.realign", function(v) trace_realign = v end)

local nofrealigned     = 0

--                leftskip   rightskip parfillskip
-- raggedleft      0 +         0          -
-- raggedright     0           0         fil
-- raggedcenter    0 +         0 +        -

local function handler(head,leftpage,realpageno)
    for current, id, subtype, list in nextlist, head do
        if subtype == linelist_code then
            local a = takeattr(current,a_realign)
            if a and a > 0 then
                local pageno = div(a,10)
                if pageno ~= realpageno then
                    local align  = a % 10
                    local action = 0
                    if align == 1 then -- flushright
                        action = leftpage and 1 or 2
                    elseif align == 2 then -- flushleft
                        action = leftpage and 2 or 1
                    end
                    -- WS: watch this
                    local direction = getdirection(current)
                    -- or should this happen at the tex end:
                    if direction == righttoleft_code then
                        if action == 1 then
                            action = 2
                        elseif action == 2 then
                            action = 1
                        end
                    end
                    -- Currently we just prepend and append which kind of spoils the normalization unless
                    -- we extend our specs and also introduce left/right anchored stuff.
                    if action == 1 then
                        local head = list
                        setlink(findtail(list),new_stretch(3)) -- append
                        setlist(current,hpack_nodes(head,getwidth(current),"exactly",direction))
                        if trace_realign then
                            report_realign("flushing left, align %a, page %a, realpage %a",align,pageno,realpageno)
                        end
                    elseif action == 2 then
                        local head = setlink(new_stretch(3),list) -- prepend
                        setlist(current,hpack_nodes(head,getwidth(current),"exactly",direction))
                        if trace_realign then
                            report_realign("flushing right, align %a, page %a, realpage %a",align,pageno,realpageno)
                        end
                    elseif trace_realign then
                        report_realign("invalid flushing, align %a, page %a, realpage %a",align,pageno,realpageno)
                    end
                    nofrealigned = nofrealigned + 1
                end
            end
        end
        handler(list,leftpage,realpageno)
    end
    return head
end

function alignments.handler(head)
    return handler(head,isleftpage(),texgetcount(c_realpageno))
end

local enabled = false

function alignments.set(n)
    if not enabled then
        enableaction("shipouts","typesetters.alignments.handler")
        enabled = true
        if trace_realign then
            report_realign("enabled")
        end
    end
    texsetattribute(a_realign,texgetcount(c_realpageno) * 10 + n)
end

interfaces.implement {
    name      = "setrealign",
    actions   = alignments.set,
    arguments = "integer",
}

statistics.register("realigning", function()
    if nofrealigned > 0 then
        return format("%s processed",nofrealigned)
    else
        return nil
    end
end)
