local curl = require "lcurl"

-- How many times curl_multi_perform should be called before hitting of CURLPAUSE_CONT.
-- (including curl_multi_perform that causes WriteFunction to pause writes,
-- i.e. 1 means that CURLPAUSE_CONT will be performed immediately after pause.)
local WAIT_COUNT   = 15

local SIZE         = 10 * 1024
-- local RESOURCE_URL = "http://httpbin.org/bytes/" .. SIZE
local RESOURCE_URL = "http://127.0.0.1:7090/bytes/" .. SIZE

local State = {
  PAUSE   = 0, -- write function should return CURL_WRITEFUNC_PAUSE
  WAIT    = 1, -- waiting for CURLPAUSE_CONT
  WRITE   = 2, -- write function should perform write
  WRITTEN = 3, -- write function have performed write
}

-- Current state
local state = State.PAUSE

-- Countdown to continue writes
local waitCount = 0

-- Received data and data size
local data, datasize = {}, 0

local function WriteFunction(str)
  if state == State.PAUSE then
    state = State.WAIT
    waitCount = WAIT_COUNT
    return curl.WRITEFUNC_PAUSE
  end

  if state == State.WAIT then
    -- callback shouldn't be called in this state
    print("WARNING: write-callback called in STATE_WAIT")
    return curl.WRITEFUNC_PAUSE
  end

  if state == State.WRITE then
    state = State.WRITTEN
  end

  datasize = datasize  + #str
  data[#data + 1] = str
end

local function perform(multi, easy)
  while true do
    local handles = multi:perform()

    if state == State.WAIT then
      waitCount = waitCount - 1
      if waitCount == 0 then
        state = State.WRITE
        easy:pause(curl.PAUSE_CONT)
      end
    end

    if state == State.WRITTEN then
      state = State.PAUSE
    end

    if 0 == handles then
      local h, ok, err = multi:info_read()
      return not not ok, err
    end

    multi:wait()
  end
end

local easy  = curl.easy{
  url             = RESOURCE_URL,
  accept_encoding = "gzip,deflate",
  writefunction   = WriteFunction,
}
local multi = curl.multi()
multi:add_handle(easy)

local ok, err = perform(multi, easy)

if ok then
  print("OK: data retrieved successfully (" .. tostring(datasize) .. ")")
else
  print("ERROR: data retrieve failed (" .. tostring(err) .. ")")
  os.exit(1)
end
