--[[
	Licensed according to the included 'LICENSE' document
	Author: Thomas Harning Jr <harningt@gmail.com>
]]
local pairs = pairs
local assert = assert

local type = type
local tostring = tostring

local table_concat = require("table").concat
local jsonutil = require("json.util")

local _ENV = nil

local defaultOptions = {
}

local modeOptions = {}

local function mergeOptions(options, mode)
	jsonutil.doOptionMerge(options, false, 'object', defaultOptions, mode and modeOptions[mode])
end

--[[
	Cleanup function to unmark a value as in the encoding process and return
	trailing results
]]
local function unmarkAfterEncode(tab, state, ...)
	state.already_encoded[tab] = nil
	return ...
end
--[[
	Encode a table as a JSON Object ( keys = strings, values = anything else )
]]
local function encodeTable(tab, options, state)
	-- Make sure this value hasn't been encoded yet
	state.check_unique(tab)
	local encode = state.encode
	local compositeEncoder = state.outputEncoder.composite
	local valueEncoder = [[
	local first = true
	for k, v in pairs(composite) do
		local ti = type(k)
		assert(ti == 'string' or ti == 'number' or ti == 'boolean', "Invalid object index type: " .. ti)
		local name = encode(tostring(k), state, true)
		if first then
			first = false
		else
			name = ',' .. name
		end
		PUTVALUE(name .. ':')
		local val = encode(v, state)
		val = val or ''
		if val then
			PUTVALUE(val)
		end
	end
	]]
	return unmarkAfterEncode(tab, state, compositeEncoder(valueEncoder, '{', '}', nil, tab, encode, state))
end

local function getEncoder(options)
	options = options and jsonutil.merge({}, defaultOptions, options) or defaultOptions
	return {
		table = function(tab, state)
			return encodeTable(tab, options, state)
		end
	}
end

local object = {
	mergeOptions = mergeOptions,
	getEncoder = getEncoder
}

return object