if not modules then modules = { } end modules ['trac-vsp'] = {
    version   = 1.001,
    optimize  = true,
    comment   = "companion to trac-vsp.mkxl",
    author    = "Hans Hagen & Mikael Sundqvist",
    copyright = "PRAGMA ADE / ConTeXt Development Team",
    license   = "see context related readme files"
}

-- This will likely change but for now we only have a simple tracer.

local nuts        = nodes.nuts
local getid       = nuts.getid
local insertafter = nuts.insertafter

local nodecodes   = nodes.nodecodes

local splitcodes  = tex.splitcodes

local splitpoints   = { }
tracers.splitpoints = splitpoints

local collected = { }

local splitshow = {
    [splitcodes.initialize] = function(where,checks,current,height,depth,extra)
        collected = {
            height = height,
            depth  = depth,
            extra  = extra,
        }
    end,
    [splitcodes.continue] = function(where,checks,current,height,depth,total,penalty)
        collected[#collected+1] = {
            where    = splitcodes[where],
            current  = current,
            location = nodecodes[getid(current)],
            height   = height,
            depth    = depth,
            total    = total,
            penalty  = penalty,
        }
    end,
    [splitcodes.check] = function(where,checks,current,height,depth,total,penalty,badness,costs)
        collected[#collected+1] = {
            where    = splitcodes[where],
            current  = current,
            location = nodecodes[getid(current)],
            height   = height,
            depth    = depth,
            total    = total,
            penalty  = penalty,
            badness  = badness,
            costs    = costs,
        }
    end,
    [splitcodes.quit] = function(where,checks,current,height,depth,total,penalty,badness,costs)
        collected[#collected+1] = {
            where    = splitcodes[where],
            current  = current,
            location = nodecodes[getid(current)],
            height   = height,
            depth    = depth,
            total    = total,
            penalty  = penalty,
            badness  = badness,
            costs    = costs,
        }
    end,
    [splitcodes.wrapup] = function(where,checks,best,height,depth,stretch,shrink)
--        local wipe = false
--        for i=1,#collected do
--            local c = collected[i]
--            if wipe then
--                c.current = false
--            elseif c.current == best then
--                wipe = true
--            end
--        end
        collected.result  = {
            best    = best,
            height  = height,
            depth   = depth,
            stretch = stretch,
            shrink  = shrink,
        }
    end,
}

local visualizevsplit = false
local f_detail        = string.formatters["%i:%s"]

function splitpoints.start(options)
    collected = { }
end

function splitpoints.stop()
    if not visualizevsplit then
        visualizevsplit = nodes.visualizers.register("vsplit","trace:dr","trace:dr",-1.5)
        nodes.visualizers.definelayer("vsplit")
    end
    local last = nil
    for i=1,#collected do
        local c = collected[i]
        local current = c.current or last
        last = current
        if current then
            local n = visualizevsplit(f_detail(i,nodecodes[getid(current)]))
            insertafter(current,current,n)
        end
    end
end

function splitpoints.typesetresult(options)
    if #collected > 0 then
        local context, ctx_NC, ctx_BC, ctx_NR, ctx_color = context, context.NC, context.BC, context.NR, context.color
        local awfulbad = tex.magicconstants.awful_bad
        local maxdimen = tex.magicconstants.max_dimen
        context.starttabulate { "|r|l|l|r|r|r|r|r|r|" }
        ctx_BC() context("n")
        ctx_BC() context("where")
        ctx_BC() context("location")
        ctx_BC() context("height")
        ctx_BC() context("depth")
        ctx_BC() context("total")
        ctx_BC() context("penalty")
        ctx_BC() context("badness")
        ctx_BC() context("costs")
        ctx_NC() ctx_NR()
        for i=1,#collected do
            local c = collected[i]
            ctx_NC() context(i)
            ctx_NC() context(c.where)
            ctx_NC() context(c.location)
            ctx_NC() context("%p",c.height)
            ctx_NC() context("%p",c.depth)
            ctx_NC() context("%p",c.total)
            ctx_NC() context(c.penalty)
            ctx_NC() context(c.badness == awfulbad and "awful" or c.badness)
            ctx_NC() context(c.costs   == awfulbad and "awful" or c.costs)
            ctx_NC() ctx_NR()
        end
        context.stoptabulate()
        context.starttabulate { "|l|r|i3l|r|" }
        ctx_BC() context("result height")  ctx_NC() context("%p",collected.result.height)
        ctx_BC() context("target  height") ctx_NC() context("%p",collected.height)         ctx_NC() ctx_NR()
        ctx_BC() context("result depth")   ctx_NC() context("%p",collected.result.depth)
        ctx_BC() context("maximum depth")  ctx_NC() if collected.depth == maxdimen then context("max") else context("%p",collected.depth) end ctx_NC() ctx_NR()
        ctx_BC() context("result stretch") ctx_NC() context("%p",collected.result.stretch)
        ctx_BC() context("extra height")   ctx_NC() context("%p",collected.extra)          ctx_NC() ctx_NR()
        ctx_BC() context("result shrink")  ctx_NC() context("%p",collected.result.shrink)
        ctx_BC()                           ctx_NC()                                        ctx_NC() ctx_NR()
        context.stoptabulate()
    end
end


local function show_vsplit_callback(where,...)
    splitshow[where](where,...)
end

callbacks.register {
    name   = "show_vsplit",
    action = show_vsplit_callback,
}
