local function fread(file)
    local f = fs.open(file,"r")
    local o = f.readAll()
    f.close()
    return o
end

local function fwrite(file,content)
    local f = fs.open(file,"w")
    f.write(content)
    f.close()
    return true
end

local loadingico = {"...",".",".."}

local progress = 0

local function centerText(text)
    local x,y = term.getSize()
    local x2,y2 = term.getCursorPos()
    term.setCursorPos((math.ceil(x / 2) - math.floor(text:len() / 2)), y2)
    term.write(text)
    term.setCursorPos(x2,y2+1)
end

local function render(txt,oY)
  local w,h = term.getSize()
  term.setCursorPos(1,math.ceil(h/2)+oY)
  centerText(txt)
end

local doUpdate

local function bootscreen()
    term.setBackgroundColor(colors.black)
    term.setTextColor(colors.cyan)
    term.clear()
    local w,h = term.getSize()
    term.setCursorPos(1,h/2-4)
    centerText("Checking for updates...")
    local frame = 1
    while true do
        if doUpdate then
            term.setBackgroundColor(colors.blue)
            term.setTextColor(colors.white)
            term.clear()
            local w,h = term.getSize()
            term.setCursorPos(1,math.ceil(h/2))
            centerText("Getting ready for updates")
            centerText("Do not turn off your computer")
            local init = false
            while true do
                render(loadingico[frame],-4)
                if progress > 0 then
                  if not init then
                    term.setBackgroundColor(colors.blue)
                    term.setTextColor(colors.white)
                    term.clear()
                    render(loadingico[frame],-4)
                    init = true
                  end
                  term.setCursorPos(1,math.ceil(h/2))
                  centerText("Working on updates")
                  centerText(math.floor(progress + 0.5).."% complete")
                  centerText("Do not turn off your computer")
                end
                frame = frame+1
                if frame > #loadingico then
                    frame = 1
                end
                os.sleep(0.25)
            end
        end
        if h > 19 then
          render(loadingico[frame],10)
        else
          render(loadingico[frame],4)
        end
        frame = frame+1
        if frame > #loadingico then
            frame = 1
        end
        os.sleep(0.25)
    end
end

local hpost = http.post

local function getField(thing,fieldname)
    if string.find(thing,"<"..fieldname..">",1,true) ~= nil and string.find(thing,"</"..fieldname..">",1,true) ~= nil then
        begin = nil
        ending = nil
        trash,begin = string.find(thing,"<"..fieldname..">",1,true)
        ending,ending2 = string.find(thing,"</"..fieldname..">",begin+1,true)
        if begin ~= nil and ending ~= nil then
            return string.sub(thing,begin+1,ending-1),string.sub(thing,1,trash-1)..string.sub(thing,ending2+1,string.len(thing))
        end
    end
    return nil
end

local function download(pth)
    local f = hpost("https://level.eu5.net/sGet.php","path="..textutils.urlEncode(pth).."&code="..textutils.urlEncode("eFIs8QuL"),{Cookie=userID}).readAll()
    if f ~= "409" and f ~= "403" and f ~= "401" then
      if pth == "startup" and f ~= fread(shell.getRunningProgram()) then
          fwrite(shell.getRunningProgram(),f)
          os.sleep(1)
          os.reboot()
        end
        if pth ~= "startup" then
          if f ~= "403" then
              fwrite(pth,f)
          else
              return false
          end
        end
        return true
    else
        return false
    end
end

local function update()
  local servertimestamp
  local clienttimestamp
  if fs.exists("version.txt") then
      clienttimestamp = tonumber(fread("version.txt"))
    end
    if not clienttimestamp then
      clienttimestamp = 0
    end
  local response,err = hpost("https://level.eu5.net/sGet.php","path="..textutils.urlEncode("").."&code="..textutils.urlEncode("eFIs8QuL"))
  if not response then
    -- could not connect
    os.sleep(0.5)
    -- put "starting in offline mode"
    return
  end
  local f = response.readAll()
  servertimestamp = tonumber((getField(f,"version")))
  if servertimestamp > clienttimestamp then
    doUpdate = true
  end
    local tFiles = 0
    local pack = "Full"

    local tree = {}
    local folders = {}
    local function searchFolder(folder)
        --print("Searching folder root/"..folder)
        local f = hpost("https://level.eu5.net/sGet.php","path="..textutils.urlEncode(folder).."&code="..textutils.urlEncode("eFIs8QuL")).readAll()
        --print(f)
        local f2 = f
        while true do
            local file = nil
            file,f = getField(f,"file")
            if not file then
                break
            else
                local name = getField(file,"name")
                local timestamp = getField(file,"timestamp")
                timestamp = tonumber(timestamp)
                --if pack == "Full" or fs.exists(fs.combine(folder,name)) or folder == "LevelOS/assets" or fs.combine(folder,name) == "startup.lua" then
                  tree[fs.combine(folder,name)] = {timestamp=timestamp}
                  tFiles = tFiles+1
                --end
                --print("Found "..fs.combine(folder,name))
            end
        end
        f = f2
        while true do
            local file = nil
            file,f = getField(f,"folder")
            if not file then
                break
            else
                local name = getField(file,"name")
                if not fs.exists(fs.combine(folder,name)) then
                    fs.makeDir(fs.combine(folder,name))
                end
                folders[fs.combine(folder,name)] = ""
                searchFolder(fs.combine(folder,name))
            end
        end
        return true
    end
    
    if doUpdate then
        if not searchFolder("") then return false end

        if tree["startup.lua"] then
          download("startup.lua")
        end

        for k,v in pairs(tree) do
            if download(k,root,v.timestamp) == true then
                progress = progress+(100/tFiles)
            end
        end
        fwrite("version.txt",tostring(servertimestamp))
        os.sleep(1)
        os.reboot()
    end
end


parallel.waitForAny(bootscreen,update)

--shell.run("rLoad")
--shell.run("rWindow")
shell.run("lUtils")
local holding = {}
function lUtils.isHolding(key)
  return holding[key] or holding[keys[key]] or false
end
local win = window.create(term.current(),1,1,term.getSize())
win.setVisible(true)
local oterm = term.current()
local cor = coroutine.create(function() shell.run("omnidrill.sgui") end)
os.startTimer(0.05)
while true do
  local e = {os.pullEventRaw()}
  if e[1] == "key" then
    holding[e[2]] = true
    --term.setCursorPos(1,1)
    --term.write(e[1])
  elseif e[1] == "key_up" then
    holding[e[2]] = nil
  end
  if e[1] ~= "timer" then
    os.startTimer(0.05)
    -- doubles events for proper render
  end
  term.redirect(win)
  coroutine.resume(cor,unpack(e))
  --term.redirect(oterm)
  --win.setVisible(true)
  --win.setVisible(false)
  local x,y = win.getCursorPos()
  local txt = win.getTextColor()
  local bg = win.getBackgroundColor()
  --[[term.setCursorPos(1,1)
  term.setTextColor(colors.red)
  lUtils.transWrite(textutils.formatTime(os.time()))
  term.setTextColor(txt)
  term.setBackgroundColor(bg)
  term.setCursorPos(x,y)]]
  term.redirect(oterm)
  win.setVisible(true)
  win.setVisible(false)
  if coroutine.status(cor) == "dead" then
    return
  end
end