mesecons_autowire.pos1 = nil
mesecons_autowire.pos2 = nil


-- a bit of a weld (TODO: fix that)
function is_circuit_element(pos)
    local node = minetest.get_node(pos)
    local name = node.name
    
    local m = string.match(name,"^mesecons_")
    if m ~= nil then 
	return true
    else
	return false
    end
end


local  function put_node(pos,node)
    minetest.set_node(pos,node)
    mesecon.on_placenode(pos,node)
end



function get_neigh_pins(p)
    return {
	u = get_pins_sticky( { x=p.x,	y=p.y,	z=p.z+1 } ).d,
	d = get_pins_sticky( { x=p.x,	y=p.y,	z=p.z-1	} ).u,
	l = get_pins_sticky( { x=p.x-1,	y=p.y,	z=p.z	} ).r,
	r = get_pins_sticky( { x=p.x+1,	y=p.y,	z=p.z	} ).l
    }
end


local map2 = {
    {{"mesecons_insulated:insulated_off",1}, {u=1,d=0,l=0,r=0}},
    {{"mesecons_insulated:insulated_off",1}, {u=0,d=1,l=0,r=0}},
    {{"mesecons_insulated:insulated_off",0}, {u=0,d=0,l=1,r=0}},
    {{"mesecons_insulated:insulated_off",0}, {u=0,d=0,l=0,r=1}},
}

function pins_to_wire(pins)
    for _,v in ipairs(mesecons_autowire.map) do
	local p = v[2]
	local name = v[1][1]
	local param2 = v[1][2]
	if( eq_pins(p,pins) ) then
	    return { name = name, param2 = param2 } 
	end
    end

    for _,v in ipairs(map2) do
	local p = v[2]
	local name = v[1][1]
	local param2 = v[1][2]

	if( eq_pins(p,pins) ) then
	    return { name = name, param2 = param2 } 
	end
    end


    return {name ="air" }
end


function merge(pos,direc)
    local node = minetest.get_node(pos)
    local name = node.name
    local param2 = node.param2

    if( (not is_wire(pos)) and (not (name == "air") )) then return end    

    -- exception (dont change)
    if ( name == "mesecons_extrawires:crossover_off" )  or
	(  name == "mesecons_extrawires:crossover_on") or 
	(  name == "mesecons_extrawires:crossover_10") or
	(  name == "mesecons_extrawires:crossover_01") 
    then 
	return
    end
    -- end of exception

    local pins = and_pins(get_pins(pos),get_neigh_pins(pos))
    local final_pins = or_pins(pins, direc_to_pin(direc))


    local node = pins_to_wire(final_pins)
    put_node(pos,node)
end

function merge_start(pos,direction_from)
    merge(pos,direction_from)
end

function merge_end(pos,direction_from)
    if( direction_from == "u" ) then
	merge(pos,"d")
    elseif( direction_from == "d" ) then
	merge(pos,"u")
    elseif( direction_from == "l" ) then
	merge(pos,"r")
    elseif( direction_from == "r" ) then
	merge(pos,"l")
    end
end

function jump(pos,direc)
    local node = minetest.get_node(pos)
    local name = node.name
    local param2 = node.param2 

    if( name == "mesecons_insulated:insulated_off" or name == "mesecons_insulated:insulated_on" ) then
        if( direc == "u" or direc == "d" ) then
	    if( param2 == 0 or param2 == 2 ) then
		put_node(pos, {name ="mesecons_extrawires:crossover_off"});
	    elseif ( param2 == 1 or param2 == 3) then
		--nothing
	    end
	elseif( direc == "l" or direc == "r" ) then
	    if( param2 == 0 or param2 == 2 ) then
		--nothing
	    elseif ( param2 == 1 or param2 == 3) then
		put_node(pos, {name ="mesecons_extrawires:crossover_off"});		
	    end
        end
    end
    if( name == "air" ) then
        if( direc == "u" or direc == "d" ) then
		put_node(pos, {name ="mesecons_insulated:insulated_off",param2=1});
	elseif( direc == "l" or direc == "r" ) then
		put_node(pos, {name ="mesecons_insulated:insulated_off",param2=0});
        end
	
    end
    
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

function make_wire(p1,p2,direc)
    local current = p1
    
    merge_start(current,direc)
    current = next_pos(current,direc)
    
    while(not eq_pos(current,p2)) do
	jump(current,direc)
	current = next_pos(current,direc)
    end
    merge_end(current,direc)    
end



function do_work()
    if(not mesecons_autowire.pos1  ) then
	return false
    end
    if(not  mesecons_autowire.pos2 ) then 
	return false
    end
    
    local pos1 = mesecons_autowire.pos1
    local pos2 = mesecons_autowire.pos2

    if( pos1.y~=pos2.y) then
	return false
    end
    if( (pos1.x==pos2.x) and (pos1.z==pos2.z) ) then
	return false
    end

    if( (pos1.x~=pos2.x) and (pos1.z~=pos2.z) ) then 
	return false
    end

    local direc = ""

    if( pos1.z == pos2.z ) then
	if( pos1.x < pos2.x ) then
	    direc = "r"    
	else
	    direc = "l"
	end
    elseif( pos1.x == pos2.x ) then
	if( pos1.z < pos2.z ) then
	    direc = "u"
	else
	    direc = "d"
	end
    end


    if( direc == "" ) then return end
    make_wire(pos1,pos2,direc)
    return true
    
end

minetest.register_craftitem("mesecons_autowire:wire", {
    description = "Tool Autowire",
    inventory_image = "tool_autowire.png",
    stack_max = 1,
    groups = { tool =1  },

    on_use = function(itemstack, user, pointed_thing) 
	
	if pointed_thing.type ~= "node"  then return end
    	local node_pos = pointed_thing.under
	if( is_circuit_element(node_pos) ) then
	    mesecons_autowire.pos1 = node_pos
	else
	    mesecons_autowire.pos1 = pointed_thing.above
	end
        
       
    end,
    on_place = function(itemstack, user, pointed_thing)
	if not pointed_thing then return end
	if pointed_thing.type ~= "node"  then return end
    	local node_pos = pointed_thing.under
	if( is_circuit_element(node_pos) ) then
	    mesecons_autowire.pos2 = node_pos
	else
	    mesecons_autowire.pos2 = pointed_thing.above
	end
	if (do_work()) then
	
        	mesecons_autowire.pos1 = mesecons_autowire.pos2
		mesecons_autowire.pos2 = nil
	end
    end
    

})

