#!/usr/bin/env amplua
--[[
 - @file nmeamux
 - ABSTRACT HERE << 
 -
 - $Id$
 -
 - (C) Copyright 2011 Amplex, fm@amplex.dk
--]]

require "stdlib"
require "Class"
local NIL = Class.NIL

local NmeaNode = Class("NmeaNode", nil, {
   mName = NIL,
   mSinks = NIL,
   mPortNo = NIL,
   mSocket = NIL,
   mListeners = NIL,
})

local NmeaFilter = Class("NmeaFilter", NmeaNode, {
   mInputs = NIL,
   mOutputs = NIL,
   mPosList = NIL,
   mNegList = NIL,
})

local NmeaPort = Class("NmeaPort", NmeaNode, {
   mPath = NIL,
   mSpeed = NIL,
   mDutyIn = NIL,
   mDutyOut = NIL,
})


local sampleConf = {
   outputs = {
      instruments = { inputs = {"p_lospeed_1", "nogps_bkhousemux", "autopilot"}, port=27001,
                      output = "p_lospeed_1" },
      --sfeed     = { inputs = { "gps_bkhousemux" },  output = "p_lospeed_2",    port=27002 }, 
      gpsfeed     = { inputs = { "gps" },             output = "p_lospeed_2",    port=27002 }, 
      garmin_nmea = { inputs = { "p_lospeed_1", "p_lospeed_2", "p_ais", "p_bkhousemux" },
                      output = "p_hispeed",                                      port=27003 },
   },
   ports = {
      p_lospeed_1  = { path = "/dev/ttyusb/mos7840-9710-7840/0",  speed=4800  , port=26001},
      p_lospeed_2  = { path = "/dev/ttyusb/mos7840-9710-7840/1",  speed=4800  , port=26002},
      p_hispeed    = { path = "/dev/ttyusb/mos7840-9710-7840/2",  speed=38400 , port=26003},
      p_gps        = { path = "/dev/ttyusb/pl2303-067b-2303/0",   speed=38400 , port=26004},
      p_ais        = { path = "/dev/ttyusb/ftdi_sio-0403-6001/0", speed=38400 , port=25001},
      p_pactor     = { path = "/dev/ttyusb/ftdi_sio-0403-d010/0", speed=9600  , port=25002},
      p_garmin1    = { path = "/dev/ttyusb/mos7840-9710-7840/3",  speed=9600  , port=25003},
      p_garmin2    = { path = "/dev/ttyS0",                       speed=9600  , port=25004},
      p_bkhousemux = { path = "/dev/ttyusb/BROOKHOUSE10-7840/3",  speed=38400 , port=25005},
      p_navtex     = { path = "/dev/ttyusb/NAVTEX-------7840/3",  speed=38400 , port=25006},
   },
   filter   = {
      nogps_bkhousemux = { inputs = { "p_bkhousemux" } , port=28001,
                           neg = { "^..RMB", "^..VDV" } },
      gps_bkhousemux   = { inputs = { "p_bkhousemux" } , port=28002,
                           pos = { "^..RMB", "^..VDV" } },
      autopilot =        { inputs = { "p_hispeed" },     port=28003, 
                           pos = { "^..XTE", "^..WPT" } },
   },
}

local nodes = {}

function configure(t)
   local inp = {}
   for nm, cfg in pairs(t.ports) do
      inp[nm] = cfg.input
      nodes[nm] = NmeaPort(nm, cfg.path, cfg.inputs, cfg.port, cfg.speed)
   end
   for nm, cfg in pairs(t.outputs) do
      inp[nm] = cfg.input
      nodes[nm] = NmeaOutput(nm, cfg.output, cfg.port, cfg.speed)
   end
   for nm, cfg in pairs(t.filter) do
      inp[nm] = cfg.input
      nodes[nm] = NmeaFilter(nm, cfg.path, cfg.port, cfg.speed)
   end

   for nm, inputs in pairs(inp) do
      for _, i in pairs(inputs) do
         nodes[i]:addSink(nodes[nm])
      end
   end
end

function startSystem()
      node:start()
   end
end

function stopSystem()
   for _,n in pairs(nodes) do
      n:stop()
   end
   nodes = {}
end

function NmeaNode:processInput(str, toListeners)
   -- Simple relay
   for _,s in pairs(self.mSinks) do s:processInput(str) end
   if toListeners or self.mRelayToListeners then
      for _,l in pairs(self.mListeners) do l:write(str) end
   end
end

function NmeaNode:addSink(new)
   -- Simple relay
   self.mSinks[new.mName] = new
end

function NmeaNode:start()
   if not self.mPortNo then return end
   -- TODO Open socket
   self.mSocket = XXXX
   self.mListeners = tnew {}
   appc.addInput(self.mSocket, function(s)
      local sock = accept()
      self.mListeners:append(sock)
      self:acceptSock(sock)
   end           
end

function NmeaPort:start()
   local fd = io.open(self.mPath)
   self.mPortReg = appc.addInput(self.mSocket, function(s)
      line = line..s:read()
end      

function NmeaPort:AcceptSock(sock)
end

function NmeaNode:stop()
   if self.mSocket then self.mSocket:close()
   for _,l in pairs(self.mListeners) do l:close() end
   self.mSocket = nil
   self.mListeners = tnew {}
end

function main()
   configure()
   startSystem()
end

return ac.ADDR_TRANSIENT, main
-- vim: set sw=3 sts=3 et nu: