local env, FILE_PATH = ...

local logfh, label, record, fake, start, starti, time, timel, seek
local pause = false
local raw = ""
local ele_id = getFieldInfo("ele").id
local ail_id = getFieldInfo("ail").id

local function toNum(x)
	if x == nil then return 0 else return tonumber(x) end
end

local function parseLine(line)
	local record = {}
	local pos = 1
	local i = 0
	while true do
		local c = string.sub(line, pos, pos)
		local startp, endp = string.find(line, ",", pos)
		if startp then
			record[i] = string.sub(line, pos, startp-1)
			pos = endp + 1
		else
			record[i] = string.sub(line,pos)
			break
		end
		i = i + 1
	end
	return record
end

local function playLog(data, config, distCalc, date)
   local gpsTemp = nil
   if logfh == nil then
      local mbase = data.etx and model.getInfo().name or string.gsub(model.getInfo().name, " ", "_")
      logfh = io.open("/LOGS/" .. mbase .. "-20" .. date .. ".csv")
      data.showMax = false
      seek = 0
   end
   if logfh ~= nil then
      local pos = string.find(raw, "\n")
      local read = nil
      local ele = getValue(ele_id) * 0.005
      local ail = getValue(ail_id)
      local speed = 0
      if ail > 940 and seek > 2 then
	 -- Pause
	 pause = true
	 start = nil
      elseif math.abs(ele) > 1 or (start ~= nil and time ~= start and (getTime() - starti) - (time - start) * 100 > 10) then
	 -- Seek forward/back
	 if not pause or ele < 0 then
	    speed = ele > 0 and math.floor(ele) or math.ceil(ele) - 2
	    seek = math.max(seek + speed, 0)
	    io.seek(logfh, seek * 400)
	    raw = ""
	    pos = nil
	    start = nil
	    pause = false
	    while pos == nil and read ~= "" do
	       read = io.read(logfh, 400)
	       raw = raw .. read
	       pos = string.find(raw, "\n")
	       seek = seek + 1
	    end
	    if pos ~= nil then
	       raw = string.sub(raw, pos + 1)
	       pos = string.find(raw, "\n")
	    end
	 end
      elseif ail < -940 then
	 -- Exit playback
	 io.close(logfh)
	 data.doLogs = false
	 return 0
      elseif pause and ail <= 940 then
	 -- Resume
	 pause = false
      elseif timel ~= nil and time - timel > 2 then
	 -- Jump to next log segment
	 start = nil
      end

      -- Load next record
      if not pause and (start == nil or speed ~= 0 or (time - start) * 100 < getTime() - starti) then
	 while pos == nil and read ~= "" do
	    read = io.read(logfh, 400)
	    raw = raw .. read
	    pos = string.find(raw, "\n")
	 end
	 if read == "" then
	    -- End of file
	    pause = true
	 else
	    -- Parse record
	    seek = seek + 1
	    if pos == nil then
	       pos = string.len(raw)
	    end
	    local ln = string.sub(raw, 0, pos)
	    raw = string.sub(raw, pos + 1)
	    record = parseLine(ln)
	 end
      end

      -- Define column labels
      if label == nil then
	 label = {}
	 for i = 0, #record do
	    local unit = string.find(record[i], "%(")
	    if unit ~= nil then
	       label[string.lower(string.sub(record[i], 0, unit - 1))] = i
	    else
	       if record[i] == "Rud" then break end
	       label[string.lower(record[i])] = i
	    end
	    if record[i] == "1RSS(dB)" then data.crsf = true end
	 end
	 fake = loadScript(FILE_PATH .. "log_" .. (data.crsf and "c" or "s") .. ".luac", env)()
      else
	 -- Fake telemetry specific to Crossfire or S.Port
	 fake(data, config, record, label, toNum)

	 -- Sync playback to clock
	 timel = time
	 time = toNum(string.sub(record[label.time], 1, 2)) * 3600 + toNum(string.sub(record[label.time], 4, 5)) * 60 + toNum(string.sub(record[label.time], 7))
	 if start == nil then
	    start = time
	    starti = getTime()
	 end

	 -- Fake telemetry that's similar on Crossfire and S.Port
	 data.time = string.sub(record[label.time], 0, 8)
	 data.altitude = toNum(record[label.alt])
	 if data.alt_id == -1 and data.gpsAltBase and data.gpsFix and data.satellites > 3000 then
	    data.altitude = data.gpsAlt - data.gpsAltBase
	 end
	 data.speed = toNum(record[label.gspd])
	 data.vspeed = toNum(record[label.vspd])
	 if data.showCurr then
	    data.current = toNum(record[label.curr])
	 end
	 if data.a4_id > -1 then
	    data.cell = toNum(record[label.a4])
	 end
	 if record[label.gps] ~= nil then
	    pos = string.find(record[label.gps], " ")
	    if pos ~= nil then
	       gpsTemp = {
		  lat = toNum(string.sub(record[label.gps], 0, pos - 1)),
		  lon = toNum(string.sub(record[label.gps], pos + 1))
	       }
	    end
	 end
	 data.telem = true
      end
   else
      data.doLogs = false
   end

   return gpsTemp
end

return playLog
