local ffi = FFI or require("ffi")

Gate = {}

function Gate.new(objref, definition)
	local gate = {
		-- Logic Critical
		in_queue = ffi.new("int[1]"),
		port_states = ffi.new("int["..(#definition.ports+1).."]"),
		logic = definition.logic,
		ports = {},
		port_nets = {},
		
		objref = objref,
		definition = definition,
	}
	return gate
end

-- Logic Critical
function Gate.getportstate(gate, index)
	return gate.port_nets[index].state
end

-- Logic Critical
function Gate.setportstate(gate, index, state)
	if state ~= gate.port_states[index] then
		local group = gate.port_nets[index]
--		local net_state_num = gate.port_net_state_nums[index]
		group.state_num = group.state_num - gate.port_states[index] + state
		gate.port_states[index] = state
		
		if ((group.state_num>0) ~= (group.state==1)) and (group.in_queue[0]==0) then
			Simulation.queuegroup(GSim, group)
		end
	end
end

-- Logic Critical
function Gate.logic(gate)
	gate.logic(gate)
end

function Gate.preinit(gate)
	
end

function Gate.initdata(gate)
	gate.data = {}
end

function Gate.getdata(gate)
	return gate.data
end

function Gate.getportisrising(gate, index)
	return Port.isrising(gate.ports[index])
end

function Gate.getportisfalling(gate, index)
	return Port.isfalling(gate.ports[index])
end

function Gate.cb(gate, ...)
	Simulation.queuecallback(GSim, gate, ...)
end

function Gate.queue(gate, delay)
	Simulation.queuegatelater(GSim, gate, delay)
end

function Gate.gettick(gate)
	return GSim.current_tick
end

function Gate.getdefinition(gate)
	return gate.definition
end

-- Logic functions

function Gate.init(gate)
	Gate.getdefinition(gate).init(gate)
end

function Gate.input(gate, argv)
	Gate.getdefinition(gate).input(gate, argv)
end