local nc, ncp, vector 
    = nc, ncp, vector
local nc_nodepref = "nc_writing:glyph"

ncp.writing = ncp.writing or {}
ncp.writing.pages = ncp.writing.pages or { nc.writing_glyphs }

for g, glyph in pairs(ncp.writing.pages[1]) do
    glyph.id = glyph.id or nc_nodepref..g
end

function ncp.writing.get_glyph(id)
    for p, page in pairs(ncp.writing.pages) do
        for g, glyph in pairs(page) do
            if id == glyph.id then 
                glyph.p = p
                glyph.g = g
                return glyph
            end
        end
    end
end

function ncp.writing.next(glyph)
    local p, g = glyph.p, glyph.g
    local page = ncp.writing.pages[p]
    local gn = g < #page and g+1 or 1
    return page[gn], p, gn
end

function ncp.writing.next_page(glyph)
    local p = glyph.p
    local pn = p < #ncp.writing.pages and p+1 or 1
    return ncp.writing.pages[pn][1], pn, 1
end

function ncp.writing.prev_page(glyph)
    local p = glyph.p
    local pn = p > 1 and p-1 or #ncp.writing.pages and p+1 or 1
    return ncp.writing.pages[pn][1], pn, 1
end

-- copied with modifications from nc_writing
function ncp.writing.register(glyph)
    local desc = glyph.name.." Charcoal Glyph"
    local tile = "nc_fire_coal_4.png^[mask:"..glyph.texture
    if (glyph.flipped) then tile = tile.."^[transformFX" end
    core.register_node(glyph.id, {
        description = desc,
        tiles = {
            tile,
            "[combine:1x1",
        },
        use_texture_alpha = "clip",
        drawtype = "nodebox",
        node_box = nc.fixedbox({
            -0.5, -15/32, -0.5, 0.5, -14/32, 0.5
        }),
        paramtype = "light",
        paramtype2 = "facedir",
        sunlight_propagates = true,
        walkable = false,
        buildable_to = true,
        pointable = false,
        groups = {
            flammable = 1,
            alpha_glyph = 1,
            cheat = 1,
        },
        drop = "nc_fire:lump_coal",
        floodable = true,
        sounds = nc.sounds("nc_terrain_crunchy"),
        on_node_touchthru = function(pos, node, under, player)
            local raw = nc.touchtip_node(under, nil, player)
            if raw and vector.equals(vector.subtract(under, pos),
                nc.facedirs[node.param2].b) then
                return desc .. raw:gsub("^ +", "")
            end
            return raw
        end,
        on_falling_check = function(pos, node)
            local dp = vector.add(pos, nc.facedirs[node.param2].b)
            if not nc.writing_writable(dp, nil, true) then
                core.remove_node(pos)
                return true
            end
            return false
        end,
        mapcolor = {r = 8, g = 8, b = 8, a = 32},
    })
end

-- copied with modifications from nc_writing
local old_punchnode
for k,v in pairs(core.registered_on_punchnodes) do
    if type(v) == "function" and debug.getinfo(v).short_src:match("nc_writing/craft.lua$") then
        old_punchnode = table.remove(core.registered_on_punchnodes, k)
        break
    end
end
if not old_punchnode then
    core.log("error", "failed to override nc_writing punchnode callback")
    do return end
end
core.register_on_punchnode(function(pos, node, puncher, pointed)
    if not (
        puncher 
        and puncher:is_player()
        and puncher:get_wielded_item():get_name() == "nc_fire:lump_coal"
        and nc.writing_writable(pos, node)
    ) then return end

    local anode = core.get_node_or_nil(pointed.above)
    if not anode then return end
    
    local glyph = ncp.writing.get_glyph(anode.name)
    if not glyph then return end

    if puncher:get_player_control().sneak then
        anode.name = ncp.writing.next_page(glyph).id
    else
        anode.name = ncp.writing.next(glyph).id
    end
    core.swap_node(pointed.above, anode)
    nc.node_sound(pointed.above, "place", { node = anode })

    if core.get_item_group(anode.name, "alpha_glyph") ~= 0 then
        local def = core.registered_items[anode.name] or {}
        if def.on_spin then def.on_spin(pointed.above, anode) end
    end
    nc.player_discover(puncher, "place:"..anode.name)
end)

-- copied with modifications from nc_writing
local old_place = core.item_place
function core.item_place(itemstack, placer, pointed, param2, ...)
    if not nc.interact(placer) or (itemstack:get_name() ~= "nc_fire:lump_coal") then
        return old_place(itemstack, placer, pointed, param2, ...)
    end

    local anode = core.get_node_or_nil(pointed.above)
    if not (
        anode
        and core.get_item_group(anode.name, "alpha_glyph") > 0
        and vector.equals(
            nc.facedirs[anode.param2].t,
            vector.subtract(pointed.above, pointed.under)
        )
    ) then 
        return old_place(itemstack, placer, pointed, param2, ...) 
    end

    local glyph = ncp.writing.get_glyph(anode.name)
    if not glyph then return end

    local sneak = placer:get_player_control().sneak
    if sneak then
        anode.name = ncp.writing.prev_page(glyph).id
    else
        local np2 = nc.writing_spinmap[anode.param2] or 0
        if np2 < anode.param2 and glyph.p == 1 and nc.writing_glyph_alts[glyph.g] then
            anode.name = nc_nodepref..nc.writing_glyph_alts[g]
        end
        anode.param2 = nc.writing_spinmap[anode.param2] or 0
    end

    core.swap_node(pointed.above, anode)
    nc.node_sound(pointed.above, "place", { node = anode })
    local def = core.registered_items[anode.name] or {}
    if def.on_spin then def.on_spin(pointed.above, anode) end

    if sneak then
        nc.player_discover(placer, "place:"..anode.name)
    else
        nc.player_discover(placer, "charcoal writing rotate") 
    end
end
