local function isIdentifier( k )
	return type( k ) == "string" and string.match( k, "^[_%a][_%w]*$" )
end

local function emitConfigurationValue( append, warnf, k, sk, v )
	if not isIdentifier( sk ) then
		warnf( "subkey %s of key %s must be a valid Lua identifier",
			tostring( sk ), tostring( k ) )
		return
	end

	local vt = type( v )
	if vt == "string" then
		append( "%s.%s = %q", k, sk, v )
	elseif vt == "number" then
		local srep
		
		-- supporting inf and ind is more to prevent those values from
		-- resulting in unparseable serialized Lua than because I expect
		-- those value types to be used frequently
		if v ~= v then
			srep = "0 / 0"
		elseif v == math.huge then
			srep = "1 / 0"
		elseif v == -math.huge then
			srep = "-1 / 0"
		else
			srep = tostring( v )
		end
		append( "%s.%s = %s", k, sk, srep )
	elseif vt == "boolean" then
		append( "%s.%s = %s", k, sk, v and "true" or "false" )
	else
		warnf( "unsupported value type %s for key %s.%s",
			tostring( v ), k, sk )
	end
end

local function emitConfigurationTable( append, warnf, k, t )
	if isIdentifier( k ) and type( t ) == "table" then
		for sk, v in pairs( t ) do
			emitConfigurationValue( append, warnf, k, sk, v )
		end
	elseif not isIdentifier( k ) then
		print( type( k ), k )
		warnf( "key %s must be a valid Lua identifier",  tostring( k ) )
	elseif type( t ) ~= "table" then
		warnf( "value %s for key %s must be a table", tostring( k ), tostring( t ) )
	end
end

-- Given a table t of the following form:
-- - top level keys are Lua identifier strings
-- - values are plain tables also with identifier keys
-- - subtables values are strings, numbers, or booleans
--
-- The serializeConfiguration function will return a
-- string that if written to a file would be readable
-- by KrConfiguration into an equivalent table.
--
-- Any keys or values found which cannot be written will
-- result in calls to the warnf function with details.
local function serializeConfiguration( t, warnf )
	local results = { "-- This file will be re-written by AgKernel, do not edit." }
	local function append( ... )
		results[ #results + 1 ] = string.format( ... )
	end
	for k, v in pairs( t ) do
		emitConfigurationTable( append, warnf, k, v )
	end
	append( "" ) -- include a trailing newline
	
	return table.concat( results, "\n" )
end



return serializeConfiguration
