-- ; -*- mode: Lua -*-
-- First, you collect necessary pieces
local A, Fi, Fo = ...

-- (1) A is an opaque structure representing our Scoring Assistant host side;
--     all you need to do with it is pass it as the first arg to all calls
--     of Fi and Fo (see below).

-- (2) Fi, a CFunction, is the proxy to get any data related to or describing
--     the montage being scored. It has the signature (think syscall):
--        Fi( A, opcode, arg1, arg2, ...)
--     These are the supported opcodes:
--      1. Informational.
local op_get_channel_list         = 1
local op_get_channel_list_of_type = 2
local op_get_channel_data         = 3
--      2. Metrics describing a page:
local op_get_psd                  = 100
local op_get_mc                   = 101
local op_get_swu                  = 102
local op_get_signal_envelope      = 103
local op_get_page_dirty           = 104

-- For convenience, here are wrappers

-- common notes:
--  (a) on error, Fi returns {false, error_string}; else, results as described below;
--  (b) all page parameters are 1-baaed.

function get_channel_list ()
   -- returns: n_channels, ch1, ch2, ...
   return Fi(A, op_get_channel_list)
end

function get_channel_list_of_type (t)
   -- args: t: signal type, e.g., "EEG", "EOG", etc.
   -- returns: n_channels, ch1, ch2, ...
   return Fi(A, op_get_channel_list_of_type, t)
end

function get_channel_data (h)
   -- args: h: channel, e.g., "Fz"
   -- returns: n_full_pages, n_total_pages, pagesize, samplerate
   return Fi(A, op_get_channel_data, h)
end

function get_psd (h, pa, pz, fa, fz)
   -- args: h: channel, e.g., "Fz",
   --       pa, pz: starting and ending pages, inclusive;
   --       fa, fz: frequncy range to extract PSD in.
   -- returns: a vector of numbers.
   return Fi(A, op_get_psd, h, pa-1, pz-1, fa, fz)
end

function get_mc (h, pa, pz, fa, _)
   -- args: h, channel, e.g., "Fz",
   --       pa, pz: start and end pages, inclusive;
   --       fa: f0 range to extract MC at.
   -- returns: a vector of numbers.
   return Fi(A, op_get_psd, h, pa-1, pz-1, fa, _)
end

function get_swu (h, pa, pz, fa, _)
   -- args: h: channel, e.g., "Fz",
   --       pa, pz: starting and ending pages, inclusive;
   --       fa: frequncy to extract SWU at.
   -- returns: a vector of numbers.
   return Fi(A, op_get_psd, h, pa-1, pz-1, fa, _)
end

function get_signal_envelope (h, p, scope, dt)
   -- args: h: channel, e.g., "Fz",
   --       p: page,
   --       scope: envelope scope (tightness) parameter, sec (1 should be OK),
   --       dt: time resolution of resulting vector
   -- returns: a vector of signal envelope breadth values, taken at dt intervals.
   return Fi(A, op_get_signal_envelope, h, p-1, scope, dt)
end

function get_page_dirty (h, p)
   -- args: h: channel, e.g., "Fz",
   --       p: page,
   -- returns: a portion [0..1] of signal on page p in channel h marked as artifact
   return Fi(A, op_get_page_dirty, h, p-1)
end


-- (3) Fo, also a CFunction, is used to deliver the scoring decision to the host

local nrem1 = 1
local nrem2 = 2
local nrem3 = 3
local nrem4 = 4
local rem   = 5
local wake  = 6
function put_score (p, s)
   -- args: p: page, 1-based
   --       s: score code as above
   -- returns: nothing
   return Fo(A, p-1, s)
end


--
-- function main
--
local cc = {get_channel_list_of_type ("EEG")}
print( string.format( "Montage has %d EEG channels", cc[1]))

local H = cc[2]
local nf, np, ps, sr = get_channel_data (H)
print( string.format( "Looking at channel %q: %d full pages (%d total) @%d sec, samplerate %d", H, nf, np, ps, sr))

local delta = {get_psd (H, 1, nf, 2, 3)}
local theta = {get_psd (H, 1, nf, 4, 8)}

local n_scored = 0
for p=1,nf-1 do
  -- dirty = get_page_dirty(H, p)
  -- if dirty > 0 then
  --   print( string.format("p %d dirty (%g)", p, dirty))
  -- end
  -- print( get_signal_envelope(H, p, 1, 1))

  if delta[p] > theta[p] * 1.5 then
     n_scored = n_scored+1
     -- print( "mark page ", p)
     put_score (p, nrem3)
  end
end

print( string.format("scored %d pages", n_scored))
print("")

return n_scored
