--
-- Helper function to extract the short name from a node's long name
--
-- e.g. "default:coble" -> "cobble"
--

local function get_short_name(long_name)
    local parts = {}

    for part in string.gmatch(long_name, '([^:]+)') do
        table.insert(parts, part)
    end

    if #parts == 2 then
        return parts[2]
    end

    return "unknown"
end


--
-- Create and register new mesecore nodes (one for the off state and one for the on state)
--

function camomese.register_mesecore_nodes(original_node_name, node_description)
    -- Make 2 copies of the original node, for the off and on states respectively
    local off_state_node = table.copy(core.registered_nodes[original_node_name])
    local on_state_node = table.copy(core.registered_nodes[original_node_name])

    -- Extract the short name from the full name of the original node
    local short_name = get_short_name(original_node_name)

    -- Set node as not a ground content node (both states)
    off_state_node.is_ground_content = false
    on_state_node.is_ground_content = false


    --
    -- Description
    --

    -- Sets the description for the off state node
    off_state_node.description = node_description

    -- Remove the description from the on state node as it isn't needed
    on_state_node.description = nil


    ---
    --- Tiles
    ---

    -- Add overlays to the off state node
    for idx, tile in ipairs(off_state_node.tiles) do
        if type(tile) == "string" then
            off_state_node.tiles[idx] = tile .. "^camomese_mesecore_off.png"
        elseif type(tile) == "table" and tile.name then
            off_state_node.tiles[idx].name = tile.name .. "^camomese_mesecore_off.png"
        end
    end

    -- Add overlays to the on state node
    for idx, tile in ipairs(on_state_node.tiles) do
        if type(tile) == "string" then
            on_state_node.tiles[idx] = tile .. "^camomese_mesecore_on.png"
        elseif type(tile) == "table" and tile.name then
            on_state_node.tiles[idx].name = tile.name .. "^camomese_mesecore_on.png"
        end
    end


    --
    -- Mesecons rules
    --

    off_state_node.mesecons = {
        conductor = {
            state = mesecon.state.off,
            rules = mesecon.rules.alldirs,
            onstate = "camomese:mesecore_" .. short_name .. "_on"
        }
    }

    on_state_node.mesecons = {
        conductor = {
            state = mesecon.state.on,
            rules = mesecon.rules.alldirs,
            offstate = "camomese:mesecore_" .. short_name
        }
    }


    --
    -- the both the off and on state nodes drops the off state node. the off
    -- state node drop property is needed in cases where the original node
    -- drops a different type of node such as in the case of default:stone
    -- dropping default:cobble.
    --

    off_state_node.drop = "camomese:mesecore_" .. short_name
    on_state_node.drop = "camomese:mesecore_" .. short_name


    --
    -- Set the on_blast property
    --

    off_state_node.on_blast = mesecon.on_blastnode
    on_state_node.on_blast = mesecon.on_blastnode


    --
    -- Register the new nodes
    --

    core.register_node("camomese:mesecore_" .. short_name, off_state_node)
    core.register_node("camomese:mesecore_" .. short_name .. "_on", on_state_node)


    --
    -- Register the recipe for the new mesecore node
    --

    core.register_craft({
        type = "shaped",
        output = "camomese:mesecore_" .. short_name .. " 8",
        recipe = {
            {original_node_name, original_node_name, original_node_name},
            {original_node_name, "default:mese_crystal_fragment", original_node_name},
            {original_node_name, original_node_name, original_node_name},
        }
    })
end


function camomese.register_digicore_node(original_node_name, node_description)
    -- Make a copy of the original node
    local new_node = table.copy(core.registered_nodes[original_node_name])

    -- Extract the short name from the full name of the original node
    local short_name = get_short_name(original_node_name)

    -- Set node as not a ground content node (both states)
    new_node.is_ground_content = false


    --
    -- Description
    --

    -- Set the description for the new node
    new_node.description = node_description


    ---
    --- Tiles
    ---

    -- Add overlays to the off state node
    for idx, tile in ipairs(new_node.tiles) do
        if type(tile) == "string" then
            new_node.tiles[idx] = tile .. "^camomese_digicore.png"
        elseif type(tile) == "table" and tile.name then
            new_node.tiles[idx].name = tile.name .. "^camomese_digicore.png"
        end
    end


    --
    -- Digiline rules
    --

    new_node.digilines = {
        wire = {
            rules = {
                { x =  0, y =  0, z = -1 },
                { x =  1, y =  0, z =  0 },
                { x = -1, y =  0, z =  0 },
                { x =  0, y =  0, z =  1 },
                { x =  0, y =  1, z =  0 },
                { x =  0, y = -1, z =  0 }
            },
        },
    }

    --
    -- The drop property is needed in cases where the original node drops a
    -- different type of node such as in the case of default:stone dropping
    -- default:cobble.
    --

    new_node.drop = "camomese:digicore_" .. short_name


    --
    -- Register the new nodes
    --

    core.register_node("camomese:digicore_" .. short_name, new_node)


    --
    -- Register the recipe for the new digicore node
    --

    core.register_craft({
        type = "shaped",
        output = "camomese:digicore_" .. short_name .. " 8",
        recipe = {
            {original_node_name, original_node_name, original_node_name},
            {original_node_name, "digilines:wire_std_00000000", original_node_name},
            {original_node_name, original_node_name, original_node_name},
        }
    })
end


function camomese.register_ghostcore_nodes(original_node_name, node_description)
    -- Make 2 copies of the original node, for the off and on states respectively
    local inactive_state_node = table.copy(core.registered_nodes[original_node_name])
    local active_state_node = table.copy(core.registered_nodes[original_node_name])

    -- Extract the short name from the full name of the original node
    local short_name = get_short_name(original_node_name)

    -- Set node as not a ground content node
    inactive_state_node.is_ground_content = false
    active_state_node.is_ground_content = false


    --
    -- Description
    --

    -- Set the description for the new node
    inactive_state_node.description = node_description

    -- Remove the description from the on state node as it isn't needed
    active_state_node.description = nil


    ---
    --- Tiles (commented out for the time being)
    ---

    -- Add overlays to the off state node
    for idx, tile in ipairs(inactive_state_node.tiles) do
        if type(tile) == "string" then
            inactive_state_node.tiles[idx] = tile .. "^[hardlight:camomese_ghostcore_dark.png"
        elseif type(tile) == "table" and tile.name then
            inactive_state_node.tiles[idx].name = tile.name .. "^[hardlight:camomese_ghostcore_dark.png"
        end
    end


    --
    -- Mesecon rules/conduction
    --

    inactive_state_node.mesecons = {conductor = {
        state = mesecon.state.off,
        rules = mesecon.rules.alldirs,
        onstate = "camomese:ghostcore_" .. short_name .. '_active'
    }}

    active_state_node.mesecons = {conductor = {
        state = mesecon.state.on,
        rules = mesecon.rules.alldirs,
        offstate = "camomese:ghostcore_" .. short_name
    }}


    --
    -- The both the active and inactive state nodes drops the inactive state
    -- node. The inactive state node drop property is needed in cases where the
    -- original node drops a different type of node such as in the case of
    -- default:stone dropping default:cobble.
    --

    inactive_state_node.drop = "camomese:ghostcore_" .. short_name
    active_state_node.drop = "camomese:ghostcore_" .. short_name


    --
    -- Set the on_blast property
    --

    inactive_state_node.on_blast = mesecon.on_blastnode
    active_state_node.on_blast = mesecon.on_blastnode


    --
    -- Set the on_construct property of the active ghostcore node to remove the node's shadow
    --

    active_state_node.on_construct = function(pos)
        -- remove shadow
        local shadowpos = vector.add(pos, vector.new(0, 1, 0))
        if (core.get_node(shadowpos).name == "air") then
            core.dig_node(shadowpos)
        end
    end


    --
    -- Set misc properties for when the ghostcore node is active
    --

    active_state_node.drawtype = "airlike"
    active_state_node.pointable = false
    active_state_node.walkable = false
    active_state_node.diggable = false
    active_state_node.sunlight_propagates = true
    active_state_node.paramtype = "light"


    --
    -- Register the new ghostcore nodes
    --

    core.register_node("camomese:ghostcore_" .. short_name, inactive_state_node)
    core.register_node("camomese:ghostcore_" .. short_name .. "_active", active_state_node)


    --
    -- Register the recipe for the new ghostcore node
    --

    core.register_craft({
        type = "shaped",
        output = "camomese:ghostcore_" .. short_name .. " 8",
        recipe = {
            {original_node_name, original_node_name, original_node_name},
            {original_node_name, "mesecons_random:ghoststone", original_node_name},
            {original_node_name, original_node_name, original_node_name},
        }
    })
end
