require "defines"

function check_cables(pole0)
	if pole0.type == "electric-pole" and global.gandalf then
		
		local wires2swap = {}
		
		local x0 = pole0.position.x
		local y0 = pole0.position.y
		local n1 = pole0.neighbours.copper
		
		for _,pole1 in pairs(n1) do
		
			local x1 = pole1.position.x
			local y1 = pole1.position.y
			local n2 = pole1.neighbours.copper
			
			for _,pole2 in pairs(n2) do
			
				local x2 = pole2.position.x
				local y2 = pole2.position.y
				
				if x0 ~= x2 or y0 ~= y2 then	--You know that saying; "the enemy of your enemy is your friend"? This is basically the same because the neightbour of the neighbour might be the first pole itself again, so we need to check that that doesn't happen.
					for _,pole3 in pairs(n1) do
					
						local x3 = pole3.position.x
						local y3 = pole3.position.y
						
						if (x1 ~= x3 or y1 ~= y3) and (x2 ~= x3 or y2 ~= y3) then
							
							local a = (y0-y3)/(x0-x3)
							local b = y0 - a*x0
							
							local c = (y1-y2)/(x1-x2)
							local d = y1 - c*x1
							
							local x = (d-b)/(a-c)
							local y = a*x+b
							
							if x0 == x3 and x1 ~= x2 then
								if x0 >= math.min(x1,x2) and x0 <= math.max(x1,x2) then
								
									local y = c*x0+d
									
									if y >= math.min(y0,y3) and y <= math.max(y0,y3) then
									
										table.insert(wires2swap,{pole0,pole3,pole1,pole2,x0,y})
									end
								end
								
							elseif x1 == x2 and x0 ~= x3 then
								if x1 >= math.min(x0,x3) and x1 <= math.max(x0,x3) then
								
									local y = a*x1+c
									
									if y >= math.min(y1,y2) and y <= math.max(y1,y2) then
									
										table.insert(wires2swap,{pole0,pole3,pole1,pole2,x1,y})
									end
								end	
								
							elseif x >= math.min(x0,x3) and x >= math.min(x1,x2) and y >= math.min(y0,y3) and y >= math.min(y1,y2) then
								if x <= math.max(x0,x3) and x <= math.max(x1,x2) and y <= math.max(y0,y3) and y <= math.max(y1,y2) then
									
									table.insert(wires2swap,{pole0,pole3,pole1,pole2,x,y})
								end
							end
						end
					end
				end	
			end
		end
		
		for _,v in ipairs(wires2swap) do
			swap_wires(v[1],v[2],v[3],v[4],v[5],v[6])
		end
	end
end

function swap_wires(p0,p1,p2,p3,x,y)
	p0.connect_neighbour(p2)
	p0.connect_neighbour(p3)
	p2.disconnect_neighbour(p3)
		
	p1.connect_neighbour(p2)
	p1.connect_neighbour(p3)
	p1.disconnect_neighbour(p0)
	
	game.surfaces[p0.surface.name].create_entity{name="flying-text", position={x,y}, force="neutral",text="Wires fixed"}
end

script.on_init(function() 
	global.gandalf = true
	global.poles = {}
end)

script.on_event(defines.events.on_built_entity, function(event)
	local entity = event.created_entity
	
	if entity.name == "wirecutter" then
	
		local player = game.get_player(event.player_index)
		
		if not player.cursor_stack.valid_for_read then 
			player.cursor_stack.set_stack{name = "wirecutter", count = 1}
		elseif player.cursor_stack.name == "wirecutter" then
			player.cursor_stack.count = player.cursor_stack.count + 1
		elseif player.insert({name = "wirecutter", count = 1}) == 0 then
			player.surface.spill_item_stack(player.position,{name = "wirecutter", count = 1})
		end
		
		local pole = entity.surface.find_entities_filtered{area = {{entity.position.x-0.5,entity.position.y-0.5},{entity.position.x+0.5,entity.position.y+0.5}}, type = "electric-pole"}[1]
		
		if pole then
			game.surfaces[pole.surface.name].create_entity{name="flying-text", position=pole.position, force="neutral",text="Pole "..#global.poles +1 .." selected"}
			table.insert(global.poles,pole)
			
			if #global.poles == 4 then
			
				local x = 0
				local y = 0
				
				for _,pole in pairs(global.poles) do
					x = x + pole.position.x/4
					y = y + pole.position.y/4
				end
				
				swap_wires(global.poles[1],global.poles[2],global.poles[3],global.poles[4],x,y)
				global.poles = {}
			end
		else
			player.print("Use these on the 4 poles which connect the crossing wires, such that the crossing wires run form pole 1 to pole 2 and from pole 3 to pole 4")
		end
		entity.destroy()
		
	else
		check_cables(entity)
	end
end)

script.on_event(defines.events.on_robot_built_entity, function(event)
	check_cables(event.created_entity)
end)

remote.add_interface("Gandalf",{
	on = function() 
		global.gandalf = true 
		for i,player in ipairs(game.players) do
			player.print("Gandalf is now on")
		end
	end,
	off = function() 
		global.gandalf = false 
		for i, player in ipairs(game.players) do
			player.print("Gandalf is now off")
		end
	end,
	toggle = function()
		global.gandalf = not global.gandalf 
		if global.gandalf then
			for i,player in pairs(game.players) do
				player.print("Gandalf is now on")
			end
		else
			for i,player in ipairs(game.players) do
				player.print("Gandalf is now off")
			end
		end
	end
	}
)