
function dump(o)
   if type(o) == 'table' then
      local s = '{ '
      for k,v in pairs(o) do
         if type(k) ~= 'number' then k = '"'..k..'"' end
         s = s .. '['..k..'] = ' .. dump(v) .. ','
      end
      return s .. '} '
   else
      return tostring(o)
   end
end


function is_wire_node(node)
    local list = {
        "mesecons_insulated:insulated_off", "mesecons_insulated:insulated_on",
	"mesecons_extrawires:corner_off", "mesecons_extrawires:corner_on",
        "mesecons_extrawires:tjunction_off", "mesecons_extrawires:tjunction_on",
        "mesecons_extrawires:crossover_off", "mesecons_extrawires:crossover_on",
        "mesecons_extrawires:crossover_10", "mesecons_extrawires:crossover_01",
        "mesecons_morewires:xjunction_off", "mesecons_morewires:xjunction_on",
 }

    local pos_name = node.name
    for i,name in ipairs(list) do
        if name == pos_name then
	    return true
        end
    end
    return false
end


function is_wire(pos)
    local list = {
        "mesecons_insulated:insulated_off", "mesecons_insulated:insulated_on",
	"mesecons_extrawires:corner_off", "mesecons_extrawires:corner_on",
        "mesecons_extrawires:tjunction_off", "mesecons_extrawires:tjunction_on",
        "mesecons_extrawires:crossover_off", "mesecons_extrawires:crossover_on",
        "mesecons_extrawires:crossover_10", "mesecons_extrawires:crossover_01",
        "mesecons_morewires:xjunction_off", "mesecons_morewires:xjunction_on",
 }

    local node = minetest.get_node(pos)
    local pos_name = node.name
    for i,name in ipairs(list) do
        if name == pos_name then
	    return true
        end
    end
    return false
end



function up_node(pos)
    return { x = pos.x, y = pos.y, z=pos.z+1}
end
function down_node(pos)
    return { x = pos.x, y = pos.y, z=pos.z-1}
end
function left_node(pos)
    return {x=pos.x-1,y=pos.y,z=pos.z}
end
function right_node(pos)
    return {x=pos.x+1,y=pos.y,z=pos.z}
end


mesecons_autowire.map = {
-- beware, order is important, I think, not sure though

    {{"air", 0 }, { u=0, d=0, l=0, r=0 }},


    {{"mesecons_insulated:insulated_off",0}, {u=0,d=0,l=1,r=1}},
    {{"mesecons_insulated:insulated_off",2}, {u=0,d=0,l=1,r=1}},
    {{"mesecons_insulated:insulated_off",1}, {u=1,d=1,l=0,r=0}},
    {{"mesecons_insulated:insulated_off",3}, {u=1,d=1,l=0,r=0}},
    
    {{"mesecons_extrawires:corner_off",0}, {u=0,d=1,l=1,r=0}},
    {{"mesecons_extrawires:corner_off",1}, {u=1,d=0,l=1,r=0}},
    {{"mesecons_extrawires:corner_off",2}, {u=1,d=0,l=0,r=1}},
    {{"mesecons_extrawires:corner_off",3}, {u=0,d=1,l=0,r=1}},

    {{"mesecons_insulated:insulated_on",0}, {u=0,d=0,l=1,r=1}},
    {{"mesecons_insulated:insulated_on",2}, {u=0,d=0,l=1,r=1}},
    {{"mesecons_insulated:insulated_on",1}, {u=1,d=1,l=0,r=0}},
    {{"mesecons_insulated:insulated_on",3}, {u=1,d=1,l=0,r=0}},
    
    {{"mesecons_extrawires:corner_on",0}, {u=0,d=1,l=1,r=0}},
    {{"mesecons_extrawires:corner_on",1}, {u=1,d=0,l=1,r=0}},
    {{"mesecons_extrawires:corner_on",2}, {u=1,d=0,l=0,r=1}},
    {{"mesecons_extrawires:corner_on",3}, {u=0,d=1,l=0,r=1}},




    {{"mesecons_morewires:xjunction_off",0}, {u=1,d=1,l=1,r=1}},
    {{"mesecons_morewires:xjunction_on",0}, {u=1,d=1,l=1,r=1}},

    {{"mesecons_extrawires:crossover_off",0}, {u=1,d=1,l=1,r=1}},
    {{"mesecons_extrawires:crossover_10",0}, {u=1,d=1,l=1,r=1}},
    {{"mesecons_extrawires:crossover_01",0}, {u=1,d=1,l=1,r=1}},
    {{"mesecons_extrawires:crossover_on",0}, {u=1,d=1,l=1,r=1}},


    {{"mesecons_extrawires:tjunction_off",0}, {u=0,d=1,l=1,r=1}},
    {{"mesecons_extrawires:tjunction_off",1}, {u=1,d=1,l=1,r=0}},
    {{"mesecons_extrawires:tjunction_off",2}, {u=1,d=0,l=1,r=1}},
    {{"mesecons_extrawires:tjunction_off",3}, {u=1,d=1,l=0,r=1}},

    {{"mesecons_extrawires:tjunction_on",0}, {u=0,d=1,l=1,r=1}},
    {{"mesecons_extrawires:tjunction_on",1}, {u=1,d=1,l=1,r=0}},
    {{"mesecons_extrawires:tjunction_on",2}, {u=1,d=0,l=1,r=1}},
    {{"mesecons_extrawires:tjunction_on",3}, {u=1,d=1,l=0,r=1}},
}

mesecons_autowire.mapsticky = {}

function is_sticky(pos)
    local node = minetest.get_node(pos)
    local name = node.name
    for i,v in ipairs(mesecons_autowire.mapsticky) do
        local name = v[1][1]
        local param2 = v[1][2]
        local pins = v[2]

        if( (name == node.name) ) then
	    return true
        end
    end
    return false

	
end


function rotate_pin(p)	
    return { u = p.l, r = p.u, d = p.r, l = p.d }
end

function rotate_pins(p,r)
    local cur = p
    local i = 0
    while( i< r) do
	cur = rotate_pin(cur)
	i = i +1
    end
    return cur
end

function map_add_gates()
    local gates = { "and", "or", "xor", "nand", "nor"}
    local states = { "on", "off" }
    local mod = "mesecons_gates"
    local pin = {u=1,d=1,r=1,l=0}

    for _,g in ipairs(gates) do 
	for r=0,3 do
	    for _,s in ipairs(states) do 
		local name = mod..":"..g.."_"..s
		
		table.insert(mesecons_autowire.mapsticky, { { name, r}, rotate_pins(pin,r) })
	    end
	end
    end

    gates = { "not", "diode" }
    pin = {u=0,d=0,l=1,r=1}

    for _,g in ipairs(gates) do 
	for r=0,3 do
	    for _,s in ipairs(states) do 
		local name = mod..":"..g.."_"..s
		
		table.insert(mesecons_autowire.mapsticky, { { name, r}, rotate_pins(pin,r) })
	    end
	end
    end

    gates = { "latch", "flipflop" }
    mod = "mesecons_regs"
    pin = { u=0,d=1,l=1,r=1 }

    for _,g in ipairs(gates) do 
	for r=0,3 do
	    for _,s in ipairs(states) do 
		local name = mod..":"..g.."_"..s
		
		table.insert(mesecons_autowire.mapsticky, { { name, r}, rotate_pins(pin,r) })
	    end
	end
    end

    gates = { "and3", "or3", "nand3", "nor3" }
    mod = "mesecons_gates3"
    pin = { u=1,d=1,l=1,r=1 }

    for _,g in ipairs(gates) do 
	for r=0,3 do
	    for _,s in ipairs(states) do 
		local name = mod..":"..g.."_"..s
		
		table.insert(mesecons_autowire.mapsticky, { { name, r}, rotate_pins(pin,r) })
	    end
	end
    end

    
end

map_add_gates()


function get_pins_sticky(pos)
    local node = minetest.get_node(pos)
    for i,v in ipairs(mesecons_autowire.map) do
        local name = v[1][1]
        local param2 = v[1][2]
        local pins = v[2]

        if( (name == node.name) and (node.param2 == param2) ) then
	    return pins
        end
    end
    for i,v in ipairs(mesecons_autowire.mapsticky) do
        local name = v[1][1]
        local param2 = v[1][2]
        local pins = v[2]

        if( (name == node.name) and (node.param2 == param2) ) then
	    return pins
        end
    end
    return {u=0,d=0,l=0,r=0}
end



function get_pins(pos)
    local node = minetest.get_node(pos)
    for i,v in ipairs(mesecons_autowire.map) do
        local name = v[1][1]
        local param2 = v[1][2]
        local pins = v[2]

        if( (name == node.name) and (node.param2 == param2) ) then
	    return pins
        end
    end
    return {u=0,d=0,l=0,r=0}
end



function eq_pins(i1,i2)
    if i1.u ~= i2.u then return false end
    if i1.d ~= i2.d then return false end
    if i1.l ~= i2.l then return false end
    if i1.r ~= i2.r then return false end
    return true
end

function and_pins(i1,i2)
    local u,d,l,r = 0,0,0,0
    if (i1.u==1) and (i2.u==1) then
	u = 1
    end
    if (i1.d==1) and (i2.d==1) then
	d = 1
    end
    if (i1.l==1) and (i2.l==1) then
	l =1 
    end
    if(i1.r==1) and (i2.r==1) then
	r=1
    end
    return { u=u,d=d,l=l,r=r }	
end

function or_pins(i1,i2)
    local u,d,l,r = 0,0,0,0
    if (i1.u==1) or (i2.u==1) then
	u = 1
    end
    if (i1.d==1) or (i2.d==1) then
	d = 1
    end
    if (i1.l==1) or (i2.l==1) then
	l =1 
    end
    if(i1.r==1) or (i2.r==1) then
	r=1
    end
    return { u=u,d=d,l=l,r=r }	    
end

function direc_to_pin(dir)
    local u,d,l,r = 0,0,0,0
    if( dir == "u" ) then u = 1; end
    if( dir == "d" ) then d = 1; end
    if( dir == "l" ) then l = 1; end
    if( dir == "r" ) then r = 1; end    
    return {u=u,d=d,l=l,r=r}
end

function next_pos(pos,direc)
    local p = pos
    if( direc == "u" ) then
	p.z = p.z + 1
    elseif( direc == "d" ) then
	p.z = p.z - 1
    elseif( direc == "l" ) then
	p.x = p.x -1
    elseif( direc == "r" ) then	
	p.x = p.x + 1 
    end
    return p
end

function eq_pos(p1,p2)
    if( (p1.x==p2.x) and (p1.y==p2.y) and (p1.z==p2.z) ) then
	return true
    else
	return false
    end
end

