--
-- If you have the LFS _init loaded then you invoke the provision by
-- executing LFS.HTTP_OTA('your server','directory','image name').  Note
-- that is unencrypted and unsigned. But the loader does validate that
-- the image file is a valid and complete LFS image before loading.
--

local host, dir, image = ...

local doRequest, firstRec, subsRec, finalise
local n, total, size = 0, 0

doRequest = function(socket, hostIP) -- luacheck: no unused
  if hostIP then
    local con = tls.createConnection(net.TCP,0)
    -- Note that the current dev version can only accept uncompressed LFS images
    con:on("connection",function(sck)
      local request = table.concat( {
        "GET "..dir..image.." HTTP/1.1",
        "User-Agent: ESP8266 app (linux-gnu)",
        "Accept: application/octet-stream",
        "Accept-Encoding: identity",
        "Host: "..host,
        "Connection: close",
        "", "", }, "\r\n")
        print(request)
        sck:send(request)
        sck:on("receive",firstRec)
      end)
    con:connect(80,hostIP)
  end
end

firstRec = function (sck,rec)
  -- Process the headers; only interested in content length
  local i      = rec:find('\r\n\r\n',1,true) or 1
  local header = rec:sub(1,i+1):lower()
  size         = tonumber(header:match('\ncontent%-length: *(%d+)\r') or 0)
  print(rec:sub(1, i+1))
  if size > 0 then
    sck:on("receive",subsRec)
    file.open(image, 'w')
    subsRec(sck, rec:sub(i+4))
  else
    sck:on("receive", nil)
    sck:close()
    print("GET failed")
  end
end

subsRec = function(sck,rec)
  total, n = total + #rec, n + 1
  if n % 4 == 1 then
    sck:hold()
    node.task.post(0, function() sck:unhold() end)
  end
  uart.write(0,('%u of %u, '):format(total, size))
  file.write(rec)
  if total == size then finalise(sck) end
end

finalise = function(sck)
  file.close()
  sck:on("receive", nil)
  sck:close()
  local s = file.stat(image)
  if (s and size == s.size) then
    wifi.setmode(wifi.NULLMODE, false)
    collectgarbage();collectgarbage()
      -- run as separate task to maximise RAM available
    node.task.post(function() node.flashreload(image) end)
  else
    print"Invalid save of image file"
  end
end

net.dns.resolve(host, doRequest)