local repoRoot = "https://git.colon-three.com/kodi/snowier/raw/branch/main/"

local URLs = {
  fileIndex = repoRoot .. "index.json",
  sha256 = repoRoot .. "sha256.lua"
}

local log = {}

--- @param value string
function log.info(value)
  print("[I] " .. value)
end

--- @param value string
function log.debug(value)
  print("[D] " .. value)
end

--- @param value string
function log.error(value)
    printError("[E] " .. value)
end

local function main()
  log.info("Starting installer")

  if not fs.exists("sha256.lua") then
    log.info("Downloading sha256.lua")
    local sharequest = http.get(URLs.sha256)
    local shafile = fs.open("sha256.lua", "w")
    shafile.write(sharequest.readAll())
    shafile.close()
    sharequest.close()
  end
  package.path = package.path .. ";/?;/?.lua" -- hack to solve 'wget run'
  local hash = require("sha256")

  log.info("Downloading index file")
  local indexrequest = http.get(URLs.fileIndex)
  local index = textutils.unserializeJSON(indexrequest.readAll())
  indexrequest.close()

  if (index == nil) then
    log.error("Failed to deserialize index file.")
    return
  end

  log.info("Checking for updates")
  local toDownload = {}
  for k, v in ipairs(index) do
    -- A file should be redownloaded if it either:
    -- - Doesn't exist locally
    -- - Exists locally but has a different hash
    if not fs.exists(v.dest) then
      toDownload[#toDownload+1] = v
    else
      local destfile = fs.open(v.dest, "r")
      local filehash = hash.sha256(destfile.readAll())
      destfile.close()
      if filehash ~= v.sha256 then
        toDownload[#toDownload+1] = v
      end
    end
  end

  log.info(#toDownload .. " files to download")
  for k, v in ipairs(toDownload) do
    if not fs.exists("/tmp") then
      fs.makeDir("/tmp")
    end
    log.info("Downloading '" .. v.dest .. "'")
    local filerequest = http.get(repoRoot .. v.src)
    local tempfile = fs.open("/tmp/" .. v.hash .. ".lua", "w")
    tempfile.write(filerequest.readAll())
    filerequest.close()
    tempfile.close()
    -- Check the validity of the hash, this acts both as a checksum
    -- and a way to raise an error if the index is incorrect
    tempfile = fs.open("/tmp/" .. v.hash .. ".lua", "r")
    local filehash = hash.sha256(tempfile.readAll())
    tempfile.close()
    if filehash ~= v.hash then
      log.error("File " .. v.dest .. " (from " .. v.src .. ") has a mismatched hash.")
      log.error("Installation aborted.")
      return
    end
  end

  log.info("Installing")
  for k, v in ipairs(toDownload) do
    fs.move("/tmp/" .. v.hash .. ".lua", v.dest)
  end

  log.info("Installation complete!")
end

main()