-- -----------------------------------------------------------------------------
-- SimNetwork
-- simulation.lua
-- Simulation Engine
-- -----------------------------------------------------------------------------

if not SimNetwork_DATA		then dofile("data.lua") end

SimNetwork_SIMULATION = true

Sim = {
	-- list of all customers in game
	customers = {},
	
	-- list of all cable in game
	cables = {},
	
	-- list of all routers in game
	routers = {}
}

function calculateLinkCost()
end

function pickMinDistanceNode()

	local minNode = nil
	local nodeType = nil
	
	-- find customer with minimum distance
	for key, customer in Sim.customers do
		if not customer.explored then
			if minNode == nil then
				nodeType = "customer"
				minNode = customer
			elseif minNode.cost > customer.cost then
				nodeType = "customer"
				minNode = customer
			end
		end
	end
	
	-- find router with minimum distance
	for key, router in Sim.routers do
		if not router.explored then
			if minNode == nil then
				nodeType = "router"
				minNode = router
			elseif minNode.cost < router.cost then
				nodeType = "router"
				minNode = router
			end
		end
	end
	
	return minNode, nodeType
end

-- -----------------------------------------------------------------------------
-- Function: calculatePeerConnections()
-- Inputs: Customer
-- Outputs: table of Connections
-- Loops over the peers of the given Customer and calculates the shortest path
-- between the given customer and all of his peers. Returns a table of
-- Connections. Each Connection describes the quality of the link in terms of
-- 'latency', 'bottleneck'

function calcPeerConnections(customer)
	
	local peerConnections = {}
	-- initialize table peerConnections: this table will hold the information
	-- about the quality of connections between 'customer' and each of its
	-- peers. Table will be indexed from 1 to # of peers.
	for key, peer in customer.peers do
		table.insert(peerConnections, {ptrPeer = peer, connection = Connection:new(self, peer)})
	end
	local nodesToExplore = table.getn(Sim.customers) + table.getn(Sim.routers)
	
	-- ** Dijksta starts here
	-- set the distance to all nodes in topology graph to INFINITY
	for key, customer in Sim.customers do
		customer.cost = INFINITY
		customer.explored = false
	end
	for key, value in Sim.routers do
		router.cost = INFINITY
		router.explored = false
	end
	
	customer.distance = 0
	while nodesToExplore > 0 do
		-- pick node with minimum distance
		local minNode = pickMinDistanceNode()
		minNode.explored = true
		nodesToExplore = nodesToExplore - 1
		
		if minNode.cost == INFINITY then
			-- we have explored all connected nodes
			-- the rest are not connected to customer, stop
			-- the algorithm
			return peerConnections
		end
		
		-- is this node a peer?
		for key, peer in customers.peers do
			if minNode == ptrPeer then
				-- yes, update cost
				peer.connection.cost = minNode.cost
			end
		end
				
		-- if this is a router, follow outgoing connections
		if nodeType == "router" then
			for key, conn in minNode.connections do
				local linkCost = calculateLinkCost(conn.cable)
				if conn.element.cost > minNode.cost + linkCost then
					conn.element.cost = minNode.cost + linkCost
				end
			end
		end
	end
	
	return peerConnections

end


