-- Code generated by codegen/generate-rest.go. DO NOT EDIT.

--[[--
The Satori client SDK for Defold.

@module satori
]]


local log = require "nakama.util.log"
local retries = require "nakama.util.retries"
local async = require "nakama.util.async"
local api_session = require "nakama.session"
local socket = require "nakama.socket"
local json = require "nakama.util.json"
local uri = require "nakama.util.uri"
local uri_encode = uri.encode

local M = {}

-- cancellation tokens associated with a coroutine
local cancellation_tokens = {}

-- cancel a cancellation token
function M.cancel(token)
	assert(token)
	token.cancelled = true
end

-- create a cancellation token
-- use this to cancel an ongoing API call or a sequence of API calls
-- @return token Pass the token to a call to nakama.sync() or to any of the API calls
function M.cancellation_token()
	local token = {
		cancelled = false
	}
	function token.cancel()
		token.cancelled = true
	end
	return token
end

-- Private
-- Run code within a coroutine
-- @param fn The code to run
-- @param cancellation_token Optional cancellation token to cancel the running code
function M.sync(fn, cancellation_token)
	assert(fn)
	local co = nil
	co = coroutine.create(function()
		cancellation_tokens[co] = cancellation_token
		fn()
		cancellation_tokens[co] = nil
	end)
	local ok, err = coroutine.resume(co)
	if not ok then
		log(err)
		cancellation_tokens[co] = nil
	end
end

-- http request helper used to reduce code duplication in all API functions below
local function http(client, callback, url_path, query_params, method, post_data, retry_policy, cancellation_token, handler_fn)
	if callback then
		log(url_path, "with callback")
		client.engine.http(client.config, url_path, query_params, method, post_data, retry_policy, cancellation_token, function(result)
			if not cancellation_token or not cancellation_token.cancelled then
				callback(handler_fn(result))
			end
		end)
	else
		log(url_path, "with coroutine")
		local co = coroutine.running()
		assert(co, "You must be running this from withing a coroutine")

		-- get cancellation token associated with this coroutine
		cancellation_token = cancellation_tokens[co]
		if cancellation_token and cancellation_token.cancelled then
			cancellation_tokens[co] = nil
			return
		end

		return async(function(done)
			client.engine.http(client.config, url_path, query_params, method, post_data, retry_policy, cancellation_token, function(result)
				if cancellation_token and cancellation_token.cancelled then
					cancellation_tokens[co] = nil
					return
				end
				done(handler_fn(result))
			end)
		end)
	end
end

--
-- Enums
--


--
-- Objects
--

--- create_api_authenticate_logout_request
-- Log out a session, invalidate a refresh token, or log out all sessions/refresh tokens for a user.
-- @param refresh_token_str (string) Refresh token to invalidate.
-- @param token_str (string) Session token to log out.
function M.create_api_authenticate_logout_request(refresh_token_str,token_str,_)
	assert(not refresh_token_str or type(refresh_token_str) == "string", "Argument 'refresh_token_str' must be 'nil' or of type 'string'")
	assert(not token_str or type(token_str) == "string", "Argument 'token_str' must be 'nil' or of type 'string'")
	return {
		["refresh_token"] = refresh_token_str,
		["token"] = token_str,
	}
end

--- create_api_authenticate_refresh_request
-- Authenticate against the server with a refresh token.
-- @param refresh_token_str (string) Refresh token.
function M.create_api_authenticate_refresh_request(refresh_token_str,_)
	assert(not refresh_token_str or type(refresh_token_str) == "string", "Argument 'refresh_token_str' must be 'nil' or of type 'string'")
	return {
		["refresh_token"] = refresh_token_str,
	}
end

--- create_api_authenticate_request
-- 
-- @param custom_obj (table) Optional custom properties to update with this call.
--If not set, properties are left as they are on the server.
-- @param default_obj (table) Optional default properties to update with this call.
--If not set, properties are left as they are on the server.
-- @param id_str (string) Identity ID. Must be between eight and 128 characters (inclusive).
--Must be an alphanumeric string with only underscores and hyphens allowed.
function M.create_api_authenticate_request(custom_obj,default_obj,id_str,_)
	assert(not custom_obj or type(custom_obj) == "table", "Argument 'custom_obj' must be 'nil' or of type 'table'")
	assert(not default_obj or type(default_obj) == "table", "Argument 'default_obj' must be 'nil' or of type 'table'")
	assert(not id_str or type(id_str) == "string", "Argument 'id_str' must be 'nil' or of type 'string'")
	return {
		["custom"] = custom_obj,
		["default"] = default_obj,
		["id"] = id_str,
	}
end

--- create_api_event
-- A single event. Usually, but not necessarily, part of a batch.
-- @param id_str (string) Optional event ID assigned by the client, used to de-duplicate in retransmission scenarios.
--If not supplied the server will assign a randomly generated unique event identifier.
-- @param metadata_obj (table) Event metadata, if any.
-- @param name_str (string) Event name.
-- @param timestamp_str (string) The time when the event was triggered on the producer side.
-- @param value_str (string) Optional value.
function M.create_api_event(id_str,metadata_obj,name_str,timestamp_str,value_str,_)
	assert(not id_str or type(id_str) == "string", "Argument 'id_str' must be 'nil' or of type 'string'")
	assert(not metadata_obj or type(metadata_obj) == "table", "Argument 'metadata_obj' must be 'nil' or of type 'table'")
	assert(not name_str or type(name_str) == "string", "Argument 'name_str' must be 'nil' or of type 'string'")
	assert(not timestamp_str or type(timestamp_str) == "string", "Argument 'timestamp_str' must be 'nil' or of type 'string'")
	assert(not value_str or type(value_str) == "string", "Argument 'value_str' must be 'nil' or of type 'string'")
	return {
		["id"] = id_str,
		["metadata"] = metadata_obj,
		["name"] = name_str,
		["timestamp"] = timestamp_str,
		["value"] = value_str,
	}
end

--- create_api_event_request
-- 
-- @param events_arr (table) Some number of events produced by a client.
function M.create_api_event_request(events_arr,_)
	assert(not events_arr or type(events_arr) == "table", "Argument 'events_arr' must be 'nil' or of type 'table'")
	return {
		["events"] = events_arr,
	}
end

--- create_api_experiment
-- An experiment that this user is partaking.
-- @param name_str (string) 
-- @param value_str (string) Value associated with this Experiment.
function M.create_api_experiment(name_str,value_str,_)
	assert(not name_str or type(name_str) == "string", "Argument 'name_str' must be 'nil' or of type 'string'")
	assert(not value_str or type(value_str) == "string", "Argument 'value_str' must be 'nil' or of type 'string'")
	return {
		["name"] = name_str,
		["value"] = value_str,
	}
end

--- create_api_experiment_list
-- All experiments that this identity is involved with.
-- @param experiments_arr (table) All experiments for this identity.
function M.create_api_experiment_list(experiments_arr,_)
	assert(not experiments_arr or type(experiments_arr) == "table", "Argument 'experiments_arr' must be 'nil' or of type 'table'")
	return {
		["experiments"] = experiments_arr,
	}
end

--- create_api_flag
-- Feature flag available to the identity.
-- @param condition_changed_bool (boolean) Whether the value for this flag has conditionally changed from the default state.
-- @param name_str (string) 
-- @param value_str (string) Value associated with this flag.
function M.create_api_flag(condition_changed_bool,name_str,value_str,_)
	assert(not condition_changed_bool or type(condition_changed_bool) == "boolean", "Argument 'condition_changed_bool' must be 'nil' or of type 'boolean'")
	assert(not name_str or type(name_str) == "string", "Argument 'name_str' must be 'nil' or of type 'string'")
	assert(not value_str or type(value_str) == "string", "Argument 'value_str' must be 'nil' or of type 'string'")
	return {
		["condition_changed"] = condition_changed_bool,
		["name"] = name_str,
		["value"] = value_str,
	}
end

--- create_api_flag_list
-- 
-- @param flags_arr (table) 
function M.create_api_flag_list(flags_arr,_)
	assert(not flags_arr or type(flags_arr) == "table", "Argument 'flags_arr' must be 'nil' or of type 'table'")
	return {
		["flags"] = flags_arr,
	}
end

--- create_api_get_message_list_response
-- A response containing all the messages for an identity.
-- @param cacheable_cursor_str (string) Cacheable cursor to list newer messages. Durable and designed to be stored, unlike next/prev cursors.
-- @param messages_arr (table) The list of messages.
-- @param next_cursor_str (string) The cursor to send when retrieving the next page, if any.
-- @param prev_cursor_str (string) The cursor to send when retrieving the previous page, if any.
function M.create_api_get_message_list_response(cacheable_cursor_str,messages_arr,next_cursor_str,prev_cursor_str,_)
	assert(not cacheable_cursor_str or type(cacheable_cursor_str) == "string", "Argument 'cacheable_cursor_str' must be 'nil' or of type 'string'")
	assert(not messages_arr or type(messages_arr) == "table", "Argument 'messages_arr' must be 'nil' or of type 'table'")
	assert(not next_cursor_str or type(next_cursor_str) == "string", "Argument 'next_cursor_str' must be 'nil' or of type 'string'")
	assert(not prev_cursor_str or type(prev_cursor_str) == "string", "Argument 'prev_cursor_str' must be 'nil' or of type 'string'")
	return {
		["cacheable_cursor"] = cacheable_cursor_str,
		["messages"] = messages_arr,
		["next_cursor"] = next_cursor_str,
		["prev_cursor"] = prev_cursor_str,
	}
end

--- create_api_identify_request
-- Enrich/replace the current session with a new ID.
-- @param custom_obj (table) Optional custom properties to update with this call.
--If not set, properties are left as they are on the server.
-- @param default_obj (table) Optional default properties to update with this call.
--If not set, properties are left as they are on the server.
-- @param id_str (string) Identity ID to enrich the current session and return a new session. Old session will no longer be usable.
function M.create_api_identify_request(custom_obj,default_obj,id_str,_)
	assert(not custom_obj or type(custom_obj) == "table", "Argument 'custom_obj' must be 'nil' or of type 'table'")
	assert(not default_obj or type(default_obj) == "table", "Argument 'default_obj' must be 'nil' or of type 'table'")
	assert(not id_str or type(id_str) == "string", "Argument 'id_str' must be 'nil' or of type 'string'")
	return {
		["custom"] = custom_obj,
		["default"] = default_obj,
		["id"] = id_str,
	}
end

--- create_api_live_event
-- A single live event.
-- @param active_end_time_sec_str (string) End time of current event run.
-- @param active_start_time_sec_str (string) Start time of current event run.
-- @param description_str (string) Description.
-- @param id_str (string) The live event identifier.
-- @param name_str (string) Name.
-- @param value_str (string) Event value.
function M.create_api_live_event(active_end_time_sec_str,active_start_time_sec_str,description_str,id_str,name_str,value_str,_)
	assert(not active_end_time_sec_str or type(active_end_time_sec_str) == "string", "Argument 'active_end_time_sec_str' must be 'nil' or of type 'string'")
	assert(not active_start_time_sec_str or type(active_start_time_sec_str) == "string", "Argument 'active_start_time_sec_str' must be 'nil' or of type 'string'")
	assert(not description_str or type(description_str) == "string", "Argument 'description_str' must be 'nil' or of type 'string'")
	assert(not id_str or type(id_str) == "string", "Argument 'id_str' must be 'nil' or of type 'string'")
	assert(not name_str or type(name_str) == "string", "Argument 'name_str' must be 'nil' or of type 'string'")
	assert(not value_str or type(value_str) == "string", "Argument 'value_str' must be 'nil' or of type 'string'")
	return {
		["active_end_time_sec"] = active_end_time_sec_str,
		["active_start_time_sec"] = active_start_time_sec_str,
		["description"] = description_str,
		["id"] = id_str,
		["name"] = name_str,
		["value"] = value_str,
	}
end

--- create_api_live_event_list
-- List of Live events.
-- @param live_events_arr (table) Live events.
function M.create_api_live_event_list(live_events_arr,_)
	assert(not live_events_arr or type(live_events_arr) == "table", "Argument 'live_events_arr' must be 'nil' or of type 'table'")
	return {
		["live_events"] = live_events_arr,
	}
end

--- create_api_message
-- A scheduled message.
-- @param consume_time_str (string) The time the message was consumed by the identity.
-- @param create_time_str (string) The time the message was created.
-- @param metadata_obj (table) A key-value pairs of metadata.
-- @param read_time_str (string) The time the message was read by the client.
-- @param schedule_id_str (string) The identifier of the schedule.
-- @param send_time_str (string) The send time for the message.
-- @param text_str (string) The message's text.
-- @param update_time_str (string) The time the message was updated.
function M.create_api_message(consume_time_str,create_time_str,metadata_obj,read_time_str,schedule_id_str,send_time_str,text_str,update_time_str,_)
	assert(not consume_time_str or type(consume_time_str) == "string", "Argument 'consume_time_str' must be 'nil' or of type 'string'")
	assert(not create_time_str or type(create_time_str) == "string", "Argument 'create_time_str' must be 'nil' or of type 'string'")
	assert(not metadata_obj or type(metadata_obj) == "table", "Argument 'metadata_obj' must be 'nil' or of type 'table'")
	assert(not read_time_str or type(read_time_str) == "string", "Argument 'read_time_str' must be 'nil' or of type 'string'")
	assert(not schedule_id_str or type(schedule_id_str) == "string", "Argument 'schedule_id_str' must be 'nil' or of type 'string'")
	assert(not send_time_str or type(send_time_str) == "string", "Argument 'send_time_str' must be 'nil' or of type 'string'")
	assert(not text_str or type(text_str) == "string", "Argument 'text_str' must be 'nil' or of type 'string'")
	assert(not update_time_str or type(update_time_str) == "string", "Argument 'update_time_str' must be 'nil' or of type 'string'")
	return {
		["consume_time"] = consume_time_str,
		["create_time"] = create_time_str,
		["metadata"] = metadata_obj,
		["read_time"] = read_time_str,
		["schedule_id"] = schedule_id_str,
		["send_time"] = send_time_str,
		["text"] = text_str,
		["update_time"] = update_time_str,
	}
end

--- create_api_properties
-- Properties associated with an identity.
-- @param computed_obj (table) Event computed properties.
-- @param custom_obj (table) Event custom properties.
-- @param default_obj (table) Event default properties.
function M.create_api_properties(computed_obj,custom_obj,default_obj,_)
	assert(not computed_obj or type(computed_obj) == "table", "Argument 'computed_obj' must be 'nil' or of type 'table'")
	assert(not custom_obj or type(custom_obj) == "table", "Argument 'custom_obj' must be 'nil' or of type 'table'")
	assert(not default_obj or type(default_obj) == "table", "Argument 'default_obj' must be 'nil' or of type 'table'")
	return {
		["computed"] = computed_obj,
		["custom"] = custom_obj,
		["default"] = default_obj,
	}
end

--- create_api_session
-- A session.
-- @param properties_api_properties (table) Properties associated with this identity.
-- @param refresh_token_str (string) Refresh token.
-- @param token_str (string) Token credential.
function M.create_api_session(properties_api_properties,refresh_token_str,token_str,_)
	assert(not properties_api_properties or type(properties_api_properties) == "table", "Argument 'properties_api_properties' must be 'nil' or of type 'table'")
	assert(not refresh_token_str or type(refresh_token_str) == "string", "Argument 'refresh_token_str' must be 'nil' or of type 'string'")
	assert(not token_str or type(token_str) == "string", "Argument 'token_str' must be 'nil' or of type 'string'")
	return {
		["properties"] = properties_api_properties,
		["refresh_token"] = refresh_token_str,
		["token"] = token_str,
	}
end

--- create_api_update_properties_request
-- Update Properties associated with this identity.
-- @param custom_obj (table) Event custom properties.
-- @param default_obj (table) Event default properties.
-- @param recompute_bool (boolean) Informs the server to recompute the audience membership of the identity.
function M.create_api_update_properties_request(custom_obj,default_obj,recompute_bool,_)
	assert(not custom_obj or type(custom_obj) == "table", "Argument 'custom_obj' must be 'nil' or of type 'table'")
	assert(not default_obj or type(default_obj) == "table", "Argument 'default_obj' must be 'nil' or of type 'table'")
	assert(not recompute_bool or type(recompute_bool) == "boolean", "Argument 'recompute_bool' must be 'nil' or of type 'boolean'")
	return {
		["custom"] = custom_obj,
		["default"] = default_obj,
		["recompute"] = recompute_bool,
	}
end

--- create_protobuf_any
-- 
-- @param type_str (string) 
function M.create_protobuf_any(type_str,_)
	assert(not type_str or type(type_str) == "string", "Argument 'type_str' must be 'nil' or of type 'string'")
	return {
		["@type"] = type_str,
	}
end

--- create_rpc_status
-- 
-- @param code_int (number) 
-- @param details_arr (table) 
-- @param message_str (string) 
function M.create_rpc_status(code_int,details_arr,message_str,_)
	assert(not code_int or type(code_int) == "number", "Argument 'code_int' must be 'nil' or of type 'number'")
	assert(not details_arr or type(details_arr) == "table", "Argument 'details_arr' must be 'nil' or of type 'table'")
	assert(not message_str or type(message_str) == "string", "Argument 'message_str' must be 'nil' or of type 'string'")
	return {
		["code"] = code_int,
		["details"] = details_arr,
		["message"] = message_str,
	}
end

--- healthcheck
-- A healthcheck which load balancers can use to check the service.
-- @param client Client.
-- @param callback (function) Optional callback function
-- A coroutine is used and the result is returned if no callback function is provided.
-- @param retry_policy (function) Optional retry policy used specifically for this call or nil
-- @param cancellation_token (table) Optional cancellation token for this call
-- @return The result.
function M.healthcheck(client, callback, retry_policy, cancellation_token)
	assert(client, "You must provide a client")

	local url_path = "/healthcheck"

	local query_params = {}

	local post_data = nil

	return http(client, callback, url_path, query_params, "GET", post_data, retry_policy, cancellation_token, function(result)
		return result
	end)
end

--- readycheck
-- A readycheck which load balancers can use to check the service.
-- @param client Client.
-- @param callback (function) Optional callback function
-- A coroutine is used and the result is returned if no callback function is provided.
-- @param retry_policy (function) Optional retry policy used specifically for this call or nil
-- @param cancellation_token (table) Optional cancellation token for this call
-- @return The result.
function M.readycheck(client, callback, retry_policy, cancellation_token)
	assert(client, "You must provide a client")

	local url_path = "/readycheck"

	local query_params = {}

	local post_data = nil

	return http(client, callback, url_path, query_params, "GET", post_data, retry_policy, cancellation_token, function(result)
		return result
	end)
end

--- authenticate
-- Authenticate against the server.
-- @param client Client.
-- @param custom (object) Optional custom properties to update with this call.
--If not set, properties are left as they are on the server.
-- @param default (object) Optional default properties to update with this call.
--If not set, properties are left as they are on the server.
-- @param id (string) Identity ID. Must be between eight and 128 characters (inclusive).
--Must be an alphanumeric string with only underscores and hyphens allowed.

-- @param callback (function) Optional callback function
-- A coroutine is used and the result is returned if no callback function is provided.
-- @param retry_policy (function) Optional retry policy used specifically for this call or nil
-- @param cancellation_token (table) Optional cancellation token for this call
-- @return The result.
function M.authenticate(client, custom, default, id, callback, retry_policy, cancellation_token)
	assert(client, "You must provide a client")
	assert(not custom or type(custom) == "table", "Argument 'custom' must be 'nil' or of type 'table'")
	assert(not default or type(default) == "table", "Argument 'default' must be 'nil' or of type 'table'")
	assert(not id or type(id) == "string", "Argument 'id' must be 'nil' or of type 'string'")


	local url_path = "/v1/authenticate"

	local query_params = {}

	local post_data = nil
	post_data = json.encode({
	custom = custom,
	default = default,
	id = id,
	})

	return http(client, callback, url_path, query_params, "POST", post_data, retry_policy, cancellation_token, function(result)
		if not result.error and api_session then
			result = api_session.create(result)
		end
		return result
	end)
end

--- authenticate_logout
-- Log out a session, invalidate a refresh token, or log out all sessions/refresh tokens for a user.
-- @param client Client.
-- @param refreshToken (string) Refresh token to invalidate.
-- @param token (string) Session token to log out.

-- @param callback (function) Optional callback function
-- A coroutine is used and the result is returned if no callback function is provided.
-- @param retry_policy (function) Optional retry policy used specifically for this call or nil
-- @param cancellation_token (table) Optional cancellation token for this call
-- @return The result.
function M.authenticate_logout(client, refreshToken, token, callback, retry_policy, cancellation_token)
	assert(client, "You must provide a client")
	assert(not refreshToken or type(refreshToken) == "string", "Argument 'refreshToken' must be 'nil' or of type 'string'")
	assert(not token or type(token) == "string", "Argument 'token' must be 'nil' or of type 'string'")


	local url_path = "/v1/authenticate/logout"

	local query_params = {}

	local post_data = nil
	post_data = json.encode({
	refreshToken = refreshToken,
	token = token,
	})

	return http(client, callback, url_path, query_params, "POST", post_data, retry_policy, cancellation_token, function(result)
		return result
	end)
end

--- authenticate_refresh
-- Refresh a user's session using a refresh token retrieved from a previous authentication request.
-- @param client Client.
-- @param refreshToken (string) Refresh token.

-- @param callback (function) Optional callback function
-- A coroutine is used and the result is returned if no callback function is provided.
-- @param retry_policy (function) Optional retry policy used specifically for this call or nil
-- @param cancellation_token (table) Optional cancellation token for this call
-- @return The result.
function M.authenticate_refresh(client, refreshToken, callback, retry_policy, cancellation_token)
	assert(client, "You must provide a client")
	assert(not refreshToken or type(refreshToken) == "string", "Argument 'refreshToken' must be 'nil' or of type 'string'")


	local url_path = "/v1/authenticate/refresh"

	local query_params = {}

	local post_data = nil
	post_data = json.encode({
	refreshToken = refreshToken,
	})

	return http(client, callback, url_path, query_params, "POST", post_data, retry_policy, cancellation_token, function(result)
		if not result.error and api_session then
			result = api_session.create(result)
		end
		return result
	end)
end

--- event
-- Publish an event for this session.
-- @param client Client.
-- @param events (array) Some number of events produced by a client.

-- @param callback (function) Optional callback function
-- A coroutine is used and the result is returned if no callback function is provided.
-- @param retry_policy (function) Optional retry policy used specifically for this call or nil
-- @param cancellation_token (table) Optional cancellation token for this call
-- @return The result.
function M.event(client, events, callback, retry_policy, cancellation_token)
	assert(client, "You must provide a client")
	assert(not events or type(events) == "table", "Argument 'events' must be 'nil' or of type 'table'")


	local url_path = "/v1/event"

	local query_params = {}

	local post_data = nil
	post_data = json.encode({
	events = events,
	})

	return http(client, callback, url_path, query_params, "POST", post_data, retry_policy, cancellation_token, function(result)
		return result
	end)
end

--- get_experiments
-- Get or list all available experiments for this identity.
-- @param client Client.
-- @param names_arr () Experiment names; if empty string all experiments are returned.
-- @param callback (function) Optional callback function
-- A coroutine is used and the result is returned if no callback function is provided.
-- @param retry_policy (function) Optional retry policy used specifically for this call or nil
-- @param cancellation_token (table) Optional cancellation token for this call
-- @return The result.
function M.get_experiments(client, names_arr, callback, retry_policy, cancellation_token)
	assert(client, "You must provide a client")

	local url_path = "/v1/experiment"

	local query_params = {}
	query_params["names"] = names_arr

	local post_data = nil

	return http(client, callback, url_path, query_params, "GET", post_data, retry_policy, cancellation_token, function(result)
		if not result.error and api_experiment_list then
			result = api_experiment_list.create(result)
		end
		return result
	end)
end

--- get_flags
-- List all available flags for this identity.
-- @param client Client.
-- @param names_arr () Flag names; if empty string all flags are returned.
-- @param callback (function) Optional callback function
-- A coroutine is used and the result is returned if no callback function is provided.
-- @param retry_policy (function) Optional retry policy used specifically for this call or nil
-- @param cancellation_token (table) Optional cancellation token for this call
-- @return The result.
function M.get_flags(client, names_arr, callback, retry_policy, cancellation_token)
	assert(client, "You must provide a client")

	local url_path = "/v1/flag"

	local query_params = {}
	query_params["names"] = names_arr

	local post_data = nil

	return http(client, callback, url_path, query_params, "GET", post_data, retry_policy, cancellation_token, function(result)
		if not result.error and api_flag_list then
			result = api_flag_list.create(result)
		end
		return result
	end)
end

--- identify
-- Enrich/replace the current session with new identifier.
-- @param client Client.
-- @param custom (object) Optional custom properties to update with this call.
--If not set, properties are left as they are on the server.
-- @param default (object) Optional default properties to update with this call.
--If not set, properties are left as they are on the server.
-- @param id (string) Identity ID to enrich the current session and return a new session. Old session will no longer be usable.

-- @param callback (function) Optional callback function
-- A coroutine is used and the result is returned if no callback function is provided.
-- @param retry_policy (function) Optional retry policy used specifically for this call or nil
-- @param cancellation_token (table) Optional cancellation token for this call
-- @return The result.
function M.identify(client, custom, default, id, callback, retry_policy, cancellation_token)
	assert(client, "You must provide a client")
	assert(not custom or type(custom) == "table", "Argument 'custom' must be 'nil' or of type 'table'")
	assert(not default or type(default) == "table", "Argument 'default' must be 'nil' or of type 'table'")
	assert(not id or type(id) == "string", "Argument 'id' must be 'nil' or of type 'string'")


	local url_path = "/v1/identify"

	local query_params = {}

	local post_data = nil
	post_data = json.encode({
	custom = custom,
	default = default,
	id = id,
	})

	return http(client, callback, url_path, query_params, "PUT", post_data, retry_policy, cancellation_token, function(result)
		if not result.error and api_session then
			result = api_session.create(result)
		end
		return result
	end)
end

--- delete_identity
-- Delete the caller's identity and associated data.
-- @param client Client.
-- @param callback (function) Optional callback function
-- A coroutine is used and the result is returned if no callback function is provided.
-- @param retry_policy (function) Optional retry policy used specifically for this call or nil
-- @param cancellation_token (table) Optional cancellation token for this call
-- @return The result.
function M.delete_identity(client, callback, retry_policy, cancellation_token)
	assert(client, "You must provide a client")

	local url_path = "/v1/identity"

	local query_params = {}

	local post_data = nil

	return http(client, callback, url_path, query_params, "DELETE", post_data, retry_policy, cancellation_token, function(result)
		return result
	end)
end

--- get_live_events
-- List available live events.
-- @param client Client.
-- @param names_arr () Live event names; if empty string all live events are returned.
-- @param callback (function) Optional callback function
-- A coroutine is used and the result is returned if no callback function is provided.
-- @param retry_policy (function) Optional retry policy used specifically for this call or nil
-- @param cancellation_token (table) Optional cancellation token for this call
-- @return The result.
function M.get_live_events(client, names_arr, callback, retry_policy, cancellation_token)
	assert(client, "You must provide a client")

	local url_path = "/v1/live-event"

	local query_params = {}
	query_params["names"] = names_arr

	local post_data = nil

	return http(client, callback, url_path, query_params, "GET", post_data, retry_policy, cancellation_token, function(result)
		if not result.error and api_live_event_list then
			result = api_live_event_list.create(result)
		end
		return result
	end)
end

--- get_message_list
-- Get the list of messages for the identity.
-- @param client Client.
-- @param limit_int () Max number of messages to return. Between 1 and 100.
-- @param forward_bool () True if listing should be older messages to newer, false if reverse.
-- @param cursor_str () A pagination cursor, if any.
-- @param callback (function) Optional callback function
-- A coroutine is used and the result is returned if no callback function is provided.
-- @param retry_policy (function) Optional retry policy used specifically for this call or nil
-- @param cancellation_token (table) Optional cancellation token for this call
-- @return The result.
function M.get_message_list(client, limit_int, forward_bool, cursor_str, callback, retry_policy, cancellation_token)
	assert(client, "You must provide a client")

	local url_path = "/v1/message"

	local query_params = {}
	query_params["limit"] = limit_int
	query_params["forward"] = forward_bool
	query_params["cursor"] = cursor_str

	local post_data = nil

	return http(client, callback, url_path, query_params, "GET", post_data, retry_policy, cancellation_token, function(result)
		if not result.error and api_get_message_list_response then
			result = api_get_message_list_response.create(result)
		end
		return result
	end)
end

--- delete_message
-- Deletes a message for an identity.
-- @param client Client.
-- @param id_str () The identifier of the message.
-- @param callback (function) Optional callback function
-- A coroutine is used and the result is returned if no callback function is provided.
-- @param retry_policy (function) Optional retry policy used specifically for this call or nil
-- @param cancellation_token (table) Optional cancellation token for this call
-- @return The result.
function M.delete_message(client, id_str, callback, retry_policy, cancellation_token)
	assert(client, "You must provide a client")

	local url_path = "/v1/message/{id}"
	url_path = url_path:gsub("{id}", uri_encode(id_str))

	local query_params = {}

	local post_data = nil

	return http(client, callback, url_path, query_params, "DELETE", post_data, retry_policy, cancellation_token, function(result)
		return result
	end)
end

--- update_message
-- Updates a message for an identity.
-- @param client Client.
-- @param id_str () The identifier of the messages.
-- @param body (object) 
-- @param callback (function) Optional callback function
-- A coroutine is used and the result is returned if no callback function is provided.
-- @param retry_policy (function) Optional retry policy used specifically for this call or nil
-- @param cancellation_token (table) Optional cancellation token for this call
-- @return The result.
function M.update_message(client, id_str, body, callback, retry_policy, cancellation_token)
	assert(client, "You must provide a client")

	assert(body and type(body) == "object", "Argument 'body' must be of type 'object'")

	local url_path = "/v1/message/{id}"
	url_path = url_path:gsub("{id}", uri_encode(id_str))

	local query_params = {}

	local post_data = nil
	post_data = json.encode(body)

	return http(client, callback, url_path, query_params, "PUT", post_data, retry_policy, cancellation_token, function(result)
		return result
	end)
end

--- list_properties
-- List properties associated with this identity.
-- @param client Client.
-- @param callback (function) Optional callback function
-- A coroutine is used and the result is returned if no callback function is provided.
-- @param retry_policy (function) Optional retry policy used specifically for this call or nil
-- @param cancellation_token (table) Optional cancellation token for this call
-- @return The result.
function M.list_properties(client, callback, retry_policy, cancellation_token)
	assert(client, "You must provide a client")

	local url_path = "/v1/properties"

	local query_params = {}

	local post_data = nil

	return http(client, callback, url_path, query_params, "GET", post_data, retry_policy, cancellation_token, function(result)
		if not result.error and api_properties then
			result = api_properties.create(result)
		end
		return result
	end)
end

--- update_properties
-- Update identity properties.
-- @param client Client.
-- @param custom (object) Event custom properties.
-- @param default (object) Event default properties.
-- @param recompute (boolean) Informs the server to recompute the audience membership of the identity.

-- @param callback (function) Optional callback function
-- A coroutine is used and the result is returned if no callback function is provided.
-- @param retry_policy (function) Optional retry policy used specifically for this call or nil
-- @param cancellation_token (table) Optional cancellation token for this call
-- @return The result.
function M.update_properties(client, custom, default, recompute, callback, retry_policy, cancellation_token)
	assert(client, "You must provide a client")
	assert(not custom or type(custom) == "table", "Argument 'custom' must be 'nil' or of type 'table'")
	assert(not default or type(default) == "table", "Argument 'default' must be 'nil' or of type 'table'")
	assert(not recompute or type(recompute) == "boolean", "Argument 'recompute' must be 'nil' or of type 'boolean'")


	local url_path = "/v1/properties"

	local query_params = {}

	local post_data = nil
	post_data = json.encode({
	custom = custom,
	default = default,
	recompute = recompute,
	})

	return http(client, callback, url_path, query_params, "PUT", post_data, retry_policy, cancellation_token, function(result)
		return result
	end)
end


local _config = {}

--- Create a Satori client instance.
-- @param config A table of configuration options.
-- config.engine - Engine specific implementations.
-- config.host
-- config.port
-- config.timeout
-- config.use_ssl - Use secure or non-secure sockets.
-- config.bearer_token
-- config.username
-- config.password
-- @return Satori Client instance.
function M.create_client(config)
	assert(config, "You must provide a configuration")
	assert(config.host, "You must provide a host")
	assert(config.port, "You must provide a port")
	assert(config.api_key, "You must provide an api key")
	assert(config.engine, "You must provide an engine")
	assert(type(config.engine.http) == "function", "The engine must provide the 'http' function")
	assert(type(config.engine.socket_create) == "function", "The engine must provide the 'socket_create' function")
	assert(type(config.engine.socket_connect) == "function", "The engine must provide the 'socket_connect' function")
	assert(type(config.engine.socket_send) == "function", "The engine must provide the 'socket_send' function")
	log("init()")

	local client = {}
	local scheme = config.use_ssl and "https" or "http"
	client.engine = config.engine
	client.config = {}
	client.config.host = config.host
	client.config.port = config.port
	client.config.http_uri = ("%s://%s:%d"):format(scheme, config.host, config.port)
	client.config.bearer_token = config.bearer_token
	client.config.username = config.username or config.api_key
	client.config.password = config.password or ""
	client.config.timeout = config.timeout or 10
	client.config.use_ssl = config.use_ssl
	client.config.retry_policy = config.retry_policy or retries.none()

	local ignored_fns = { create_client = true, sync = true }
	for name,fn in pairs(M) do
		if not ignored_fns[name] and type(fn) == "function" then
			--log("setting " .. name)
			client[name] = function(...) return fn(client, ...) end
		end
	end

	return client
end

--- Set client bearer token.
-- @param client Satori client.
-- @param bearer_token Authorization bearer token.
function M.set_bearer_token(client, bearer_token)
	assert(client, "You must provide a client")
	client.config.bearer_token = bearer_token
end

return M
