-------------------------------------------------------------------------------
-- Copyright (c) 2017 Sierra Wireless. All rights reserved.
--
-- Contributors:
--     Randall Pfeifer - initial implementation
--
--	Interface to MP-70 BBSE emulated B&B streamer interface.
--	Provides an interface to UDP based B&B emulation that looks & feels
--	enough like a serial port to interface with the MP-170 Temeletry
--	B&B Interface emulation.
-------------------------------------------------------------------------------

-- ----------------------------------------------------------------------------
-- REQUIRES
-- ----------------------------------------------------------------------------
local socket = require 'socket'

-- ----------------------------------------------------------------------------
-- CONSTANTS/DATA
-- ----------------------------------------------------------------------------

-- ----------------------------------------------------------------------------
-- Local Functions
-- ----------------------------------------------------------------------------

------------------------------------------------------------------
-- close - Close the socket
-- 
-- Inputs:
--
-- Returns:
--
-- Notes
-- 	bbem object is useless after a close. Create a new one
------------------------------------------------------------------
local function l_close(self)
	self.socket:close()
end

------------------------------------------------------------------
-- settimeout - Set the timeout
-- 
-- Inputs:
--	timeout		-	Max time to wait, in seconds
--
-- Returns:
--
-- Notes
------------------------------------------------------------------
local function l_settimeout(self, timeout)
	return self.socket:settimeout(timeout)
end

------------------------------------------------------------------
-- write - Write data to the socket
-- 
-- Inputs:
--	data		-	String containing data. Formats not supported
--
-- Returns:
--
-- Notes
--	Never blocks
------------------------------------------------------------------
local function l_write(self, data)
--	print("send: " .. showdata(data))
	return self.socket:send(data)
end

------------------------------------------------------------------
-- read - Read data from the socket
-- 
-- Inputs:
--	len			-	Number specifying number of bytes to read
--
-- Returns:
--	String of data retrieved
--
-- Notes
-- 	Reads and accumulates data from socket as necessary. If enough
--	data has been buffered from previous read to satisfy request then
--	the data is taken from the buffer and the socket is not accessed,
--	else data is read from socket, appended to buffer, and the available
--	data is extracted from buffer and returned.
------------------------------------------------------------------
local function l_read(self, len)
	if len > string.len(self.buffer) then
		local rcv, err = self.socket:receive()
		if rcv then
--			print("recieved: " .. showdata(rcv))
			self.buffer = self.buffer .. rcv
		else
--			print("recieved: nothing")
			self.buffer = ""
			return rcv, err
		end
	end
	local rtn = string.sub(self.buffer, 1, len)
	self.buffer = string.sub(self.buffer, len + 1, -1)
	return rtn
end

local function create(addr, port)
	local bbem = {}
	
	bbem.socket = socket.udp()
	bbem.socket:setpeername(addr, port)
	bbem.buffer = ""

	bbem.close = l_close
	bbem.read = l_read
	bbem.write = l_write
	bbem.settimeout = l_settimeout
	return bbem
end

return create
