-- -------------------------------------------------------------------
-- SimNetwork
-- data.lua
-- Defines data structures of game
-- -------------------------------------------------------------------

SimNetwork_DATA = true

-- constant: Elements
-- This constant describes cables, routers, and types of customers available
-- in the game
-- Cables have 1 property: bandwidth
-- Customers have 2 properties: number of ports (p), maximum bandwidth
-- they can handle (b)
-- Customers have 4 properties: (minB
Elements = 
{
	cable = 
	{ 
		b1 = 1,			-- bandwidth
		b10 = 10,
		b100 = 100, 
		b1000 = 1000 
	},
		
	router = { 
		p2 = {p = 2, b = 5},	-- # of ports (p), maximum bandwidth (b)
		p4 = {p = 4, b = 30},
		p8 = {p = 8, b = 512},
		p16 = {p = 16, b = 10240} 
	},
	
	customer = 
	{ 
		resedential = 
		{
			-- min bandwidth (minB), max bandwidth (maxB)
			-- the actual bandwidth requirement can be
			-- any value between minB and maxB
			houses = {minB = 5, maxB = 99},
			church = {minB = 6, maxB = 10}
		},
		
		business = 
		{
			offices = {minB = 100, maxB = 300},
			corporate = {minB = 600, maxB = 2000}
		},
		
		industrial = 
		{
			library = {minB = 400, maxB = 1500},
			research = {minB = 1000, maxB = 10000},
			university = {minB = 7000, maxB = 20000}
		}
	}
		
}

-- shortcuts (i.e. say 'CABLE.b1' instead of 'Elements.cable.b1')
CABLE		= Elements.cable
ROUTER		= Elements.router
CUSTOMER	= Elements.customer
INFINITY	= 4294967295

-- class: Customer
-- Represents a customer
-- ---------------------
Customer = {}
customerMt = {__index = Customer}
function Customer:new(cusType, cusName)

	local newCustomer = {
		customerType = cusType,
		name = cusName,
		minBandwidth = nil,
		initialFee = nil,
		age = 0,
		
		peers = {},			-- graph adjacency list of pears
		connections = {},		-- adjacency list to other directly
						-- connected entities
		
		-- customer's coordinates 
		coordinates = {x = nil, y = nil},
		currentFee = nil,
		currentBandwidth = nil,
		satisfaction = 100
	}
	
	setmetatable(newCustomer, customerMt)
	return newCustomer
end

function Customer:addPeer(anotherCustomer)

	table.insert(self.peers, anotherCustomer)
	table.insert(anotherCustomer.peers, self)
end

function Customer:getLink(someElement)
	for key, value in self.connections do
		if value["element"] == someElement then
			return value["cable"]
		end
	end
	return nil
end

function Customer:addConnection(someElement, theCable)
	-- only one connection between any pair of elements can exist
	-- make sure there's previous connection to the same entity
	if self:getLink(someElement) then
		return false
	end
	
	table.insert(self.connections, {element = someElement, cable = theCable})
	table.insert(someElement.connections, {element = self, cable = theCable})
	
	return true
end

-- class: Router
-- Router's meta table
-- --------------------
Router = {}
routerMt = {__index = Router}
function Router:new()

	local newRouter = {
		routerType = nil,
		age = 0,
		coordinates = {x = nil, y = nil},
		utilization = nil
	}
	
	setmetatable(newRouter, routerMt)
	return newRouter
end

-- class: Cable
-- ------------
Cable = {}
cableMt = {}
cableMt.__index = Cable

function Cable:new(cblType)

	local newCable = {
		cableType = cblType,
		age = 0,
			
		-- a sequence of points (at least two) defining the
		-- layout of cable in the 2D floor, the first and last of which
		-- defines the end points of the cable
		points = {},
		utilization = nil
	}
	
	setmetatable(newCable, cableMt)
	return newCable
end

-- class: Connection
-- Represents a connection (possibly through multiple routers) between two 
-- elements (two customers, a router and a customer). Describes the quality
-- of the link
Connection = {}
connectionMt = {}
connectionMt.__index = Connection

function Connection:new(pointA, pointB)

	local newConnection = {
		a = pointA,	
		b = pointB,
		
		latency = INFINITY,
		bottleNeck = INFINITY,
		hops = INFINITY,

	}
	
	setmetatable(newConnection, connectionMt)
	return newConnection
end

	

