-- Minimal second-window process for src/render/DesktopScreen.lua.

local DesktopCompanion = {}

function DesktopCompanion.install(config)
  local enet = require("enet")
  local host = assert(enet.host_create())
  local peer = assert(host:connect(("127.0.0.1:%d"):format(config.port), 2))
  local image, sourceW, sourceH, preference
  local background = { 0, 0, 0, 1 }
  local connected, commandedQuit = false, false
  local pointerDown = false
  local started = love.timer.getTime()
  local lastContact = started

  local function send(kind, payload)
    if not connected then return end
    pcall(peer.send, peer, kind .. config.token .. (payload or ""), 1, "reliable")
  end

  local function receiveFrame(data)
    local prefix = "F" .. config.token .. "\n"
    if data:sub(1, #prefix) ~= prefix then return end
    local split = data:find("\n", #prefix + 1, true)
    if not split then return end
    local w, h, rgb, mode = data:sub(#prefix + 1, split - 1)
      :match("^(%d+),(%d+),(%d+),([%w_:.-]+)$")
    w, h, rgb = tonumber(w), tonumber(h), tonumber(rgb)
    if not w or not h or w < 1 or h < 1 or w > 4096 or h > 4096 then return end
    local ok, raw = pcall(love.data.decompress, "string", "lz4",
      data:sub(split + 1))
    if not ok or type(raw) ~= "string" or #raw ~= w * h * 4 then return end
    local made, pixels = pcall(love.image.newImageData, w, h, "rgba8", raw)
    if not made then return end
    if not image or sourceW ~= w or sourceH ~= h then
      if image and image.release then image:release() end
      image = love.graphics.newImage(pixels)
    else
      image:replacePixels(pixels)
    end
    sourceW, sourceH, preference = w, h, mode
    image:setFilter(mode:find("cover", 1, true) and "linear" or "nearest",
      mode:find("cover", 1, true) and "linear" or "nearest")
    background = {
      math.floor(rgb / 0x10000) % 0x100 / 255,
      math.floor(rgb / 0x100) % 0x100 / 255,
      rgb % 0x100 / 255, 1,
    }
  end

  local function service()
    while true do
      local event = host:service(0)
      if not event then break end
      if event.type == "connect" then
        connected, lastContact = true, love.timer.getTime()
        send("H")
      elseif event.type == "receive" then
        lastContact = love.timer.getTime()
        if event.data == "Q" .. config.token then
          commandedQuit = true
          love.event.quit()
        elseif event.data ~= "P" .. config.token then
          receiveFrame(event.data)
        end
      elseif event.type == "disconnect" then
        love.event.quit()
      end
    end
  end

  local function placement()
    if not image then return 0, 0, 1 end
    local ww, wh = love.graphics.getDimensions()
    local cover = preference and preference:find("cover", 1, true)
    local scale = (cover and math.max or math.min)(ww / sourceW, wh / sourceH)
    return (ww - sourceW * scale) / 2, (wh - sourceH * scale) / 2, scale
  end

  local function input(action, x, y)
    if not image then return false end
    local dx, dy, scale = placement()
    local sx, sy = math.floor((x - dx) / scale), math.floor((y - dy) / scale)
    if sx < 0 or sy < 0 or sx >= sourceW or sy >= sourceH then return false end
    send("I", ("\n%s,%d,%d"):format(action, sx, sy))
    return true
  end

  function love.update()
    service()
    local t = love.timer.getTime()
    if (not connected and t - started > 5) or t - lastContact > 5 then
      love.event.quit()
    end
  end

  function love.draw()
    love.graphics.clear(background[1], background[2], background[3], background[4])
    if not image then return end
    local x, y, scale = placement()
    love.graphics.setColor(1, 1, 1, 1)
    love.graphics.draw(image, x, y, 0, scale, scale)
  end

  function love.mousepressed(x, y, button)
    if button == 1 then pointerDown = input("down", x, y) end
  end
  function love.mousereleased(x, y, button)
    if button == 1 and pointerDown then
      if not input("up", x, y) then send("I", "\ncancel,0,0") end
      pointerDown = false
    end
  end
  function love.touchpressed(_, x, y) input("down", x, y) end
  function love.touchreleased(_, x, y) input("up", x, y) end
  function love.keypressed(key)
    if key == "escape" then love.event.quit() end
  end
  function love.quit()
    if not commandedQuit then send("C") end
    pcall(peer.disconnect_now, peer)
  end
end

return DesktopCompanion
